Perhaps my question can be a duplicate, but I'm new in powershell, and cannot figure out, what is wrong with my script, that zipping particular directories:
$path = "C:\backup\DEV82"
if(!(Test-Path -Path $path )){
New-Item -ItemType directory -Path $path
}
cd C:\inetpub\wwwroot\dev82\
$SOURCE = Get-ChildItem * -Directory|Where-Object {$_.FullName -match "App_Config|Resources|bin"}
$dtstamp = (Get-Date).ToString("yyyyMMdd_HHmmss")
Add-Type -assembly "system.io.compression.filesystem"
Foreach ($s in $SOURCE)
{
$DESTINATION = Join-path -path $path -ChildPath "$dtstamp.zip"
If(Test-path $DESTINATION) {
Remove-item $DESTINATION
}
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $DESTINATION)
}
If I execute command in $SOURCE variable, it gathers all required directories, which I want zip http://prntscr.com/j0sqri
$DESTINATION also returns valid value
PS C:\> $DESTINATION
C:\backup\DEV82\20180404_223153.zip
but right now only last folder (Resources) exists in zip file.
Ok, I rewrite my script, using, instead of Zipfile class, Compress-Archive with -Update ( -Update allows to add files\folders into existing archive )
$path = "C:\backup\DEV82"
if(!(Test-Path -Path $path )){
New-Item -ItemType directory -Path $path
}
cd C:\inetpub\wwwroot\dev82\
$SOURCE = Get-ChildItem * -Directory|Where-Object {$_.FullName -match "App_Config|Resources|bin"}
$dtstamp = (Get-Date).ToString("yyyyMMdd_HHmmss")
$DESTINATION = Join-path -path $path -ChildPath "$dtstamp.zip"
Add-Type -assembly "system.io.compression.filesystem"
If(Test-path $DESTINATION) {
Remove-item $DESTINATION
}
Foreach ($s in $SOURCE)
{
Compress-Archive -Path $s.fullname -DestinationPath $DESTINATION -Update
}
$SOURCE is already just a list of folder names, so you don't need the FullName property here:
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $DESTINATION)
Either remove it, or remove the Select-Object from the pipeline here:
$SOURCE = Get-ChildItem * -Directory |
Where-Object {$_.FullName -match "App_Config|Resources|bin"} |
Select-Object -ExpandProperty FullName
Related
I'm trying to move files (a bunch of files in a subdirectory), create a subfolder if it doesn't exist and then move the files to the subfolder
$files = Get-ChildItem -Path H:\Movies -File
# for each($file in $files){
$file = $files[0]
$filename = [io.path]::GetFileNameWithoutExtension($file)
$path= "H:\movies\" + $filename
if (!(test-path -Path $path )){ #always returns false?
New-Item -ItemType Directory -Force -Path $path
}
Move-Item $file.FullName $path
#}
I would try something like that:
$path = 'H:\Movies'
$files = Get-ChildItem -Path $path -File
foreach ($file in $files){
# Get filename without extension
$filename = $file.BaseName
# Build new folderpath
$newFolderPath = Join-Path -Path $path -ChildPath $filename
# Check if folder already exists
if (-not(Test-Path -Path $newFolderPath)) {
New-Item -Path $path -Name $filename -ItemType Directory
}
# Move file to new folder
$destination = Join-Path -Path $newFolderPath -ChildPath $file.Name
Move-Item -Path $file.FullName -Destination $destination
}
I have Tested the below code using foreach and working fine for me.
$files = Get-ChildItem -Path E:\Test -File
foreach($file in $files){
#Write-Output $file.Name
$filename = [io.path]::GetFileNameWithoutExtension($file)
Write-Output $filename
$path= "E:\Test\" + $filename
Write-Output $path
if (!(test-path -Path $path )){
Write-Output "Not Exists: $path"
#New-Item -ItemType Directory -Force -Path $path
New-Item -ItemType Directory -Path $path
}
Move-Item $file.FullName $path
}
I gave up on powershell and used file2foldergui instead
I have a small script that can successfully copy all the files from folders and subfolders and append the creation time, but the files in the subfolders do not have the creation time appended to their names.
How can I append the creation date to all files in a folder and the subfolders?
My current script is:
$path = "C:\test1"
$destination = "C:\test2"
Get-ChildItem -path $path | ForEach-Object{
$newname = $_.CreationTime.toString("yyyy-MM-dd") + $_.BaseName +$_.Extension
(Copy-Item -Recurse -Path $_.FullName -Destination ( Join-Path $destination $newname))
}
You were really close, but the -Recurse switch should have been on Get-ChildItem and within the loop you need to make sure the destination subfolder paths exist.
Try
$source = "C:\test1"
$destination = "C:\test2"
Get-ChildItem -Path $source -File -Recurse | ForEach-Object {
# create the new target folderpath for the copy
$targetPath = Join-Path -Path $destination -ChildPath $_.DirectoryName.Substring($source.Length)
# make sure the target path exists, if not create it
$null = New-Item -ItemType Directory -Path $targetPath -Force
# create a new filename with CreationDate prefixed
$newName = '{0:yyy-MM-dd}{1}{2}' -f $_.CreationTime, $_.BaseName, $_.Extension
# copy the file
$_ | Copy-Item -Destination (Join-Path -Path $targetPath -ChildPath $newname) -Force
}
While you could create your own recursive method to copy files and rename them as you go, it would be easier to use Copy-Item recursively and rename the files and folders afterwards:
$Source = "src"
$Destination = "dst"
Copy-Item -Recurse $Source $Destination
foreach ($Item in (Get-ChildItem -Recurse -File $Destination)) {
Rename-Item $Item ($Item.Name + "-" + $Item.CreationTime.toString("yyyy-MM-dd"))
}
I have a folder hierarchy with a lot of files.
I need to copy all folders and only selected files. For this purposes I write script:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" }
$Destination = "D:\test\"
Copy-Item $files -Destination $Destination -recurse
When I execute variable $files, it returns correct path:
But when I execute Copy-Item it returns not full path:
Perhaps my approach is wrong. If so, how to copy entire folder structure, and only selected files (in this case system.serviceModel.client.config file)?
UPD1 Ok, I've found, how to copy only folders:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181\"
$Destination = "D:\test\"
Copy-Item $path $Destination -Filter {PSIsContainer} -Recurse -Force
But how to copy only selected files, preserving their location? What needs to be in $Destination variable?
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" } | % { Copy-Item -Path $_.FullName -Destination $Destination }
This code would keep the directory structure the same too
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181\"
$Destination = "D:\test\"
$fileName = "system.serviceModel.client.config"
Get-ChildItem -Path $path -Recurse | ForEach-Object {
if($_.Name -like $fileName) {
$dest = "$Destination$(($_.FullName).Replace($path,''))"
$null = New-Item $dest -Force
Copy-Item -Path $_.FullName -Destination $dest -Force
}
}
To copy the whole folder structure AND files with a certain name, below code should do what you want:
$Source = 'D:\Drop\SOA-ConfigurationManagement - Test\181'
$Destination = 'D:\test'
$FileToCopy = 'system.serviceModel.client.config'
# loop through the source folder recursively and return both files and folders
Get-ChildItem -Path $Source -Recurse | ForEach-Object {
if ($_.PSIsContainer) {
# if it's a folder, create the new path from the FullName property
$targetFolder = Join-Path -Path $Destination -ChildPath $_.FullName.Substring($Source.Length)
$copyFile = $false
}
else {
# if it's a file, create the new path from the DirectoryName property
$targetFolder = Join-Path -Path $Destination -ChildPath $_.DirectoryName.Substring($Source.Length)
# should we copy this file? ($true or $false)
$copyFile = ($_.Name -like "*$FileToCopy*")
}
# create the target folder if this does not exist
if (!(Test-Path -Path $targetFolder -PathType Container)) {
$null = New-Item -Path $targetFolder -ItemType Directory
}
if ($copyFile) {
$_ | Copy-Item -Destination $targetFolder -Force
}
}
try this
$path = 'D:\Drop\SOA-ConfigurationManagement - Test\181\'
$Destination = 'D:\test\'
$files = Get-ChildItem -Path $path -Recurse -File | where Name -like "*system.serviceModel.client.config*" | %{
$Dir=$_.DirectoryName.Replace($path, $Destination)
$NewPAthFile=$_.FullName.Replace($path, $Destination)
#create dir if not exists
New-Item -Path $Dir -ItemType Directory -Force -ErrorAction SilentlyContinue
#copy file in new dir
Copy-Item $_.FullName $NewPAthFile
}
With minimal changes I'd suggest the following:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" }
$Destination = "D:\test\"
$files | % { $_ | Copy-Item -Destination $Destination -recurse }
You can even put the whole copy on one line:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$Destination = "D:\test\"
Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" } | % { $_ | Copy-Item -Destination $Destination -recurse }
Copy-Item can find the path from the stream of input objects but it doesn't seem to be able to take a collection of System.IO.FileInfo objects as an argument to Path.
I'm supposed to move data from an old server to a new one while changing the structure.
Example:
old: "C:\test\old\Data\Werkstatt\06. Aufträge\companyA\200031_Signs"
new: "C:\test\new\Data\06. Aufträge\companyA\200031_companyA_Signs"
In the old structure, the orders of a company are in a single folder.
In the new structure, all orders are to be migrated directly under the orders folder. The name consists of the order number + separator + company name + name.
current task is the folders that were successfully copied from "C:\test\old\Data\Werkstatt\06. Aufträge\%company%\" in the folder "C:\test\old\Data\Werkstatt\06. Aufträge\%company%\Z_Transfered" to move.
I tried:
$sourcepath = "C:\test\old\Data\Werkstatt\06. Aufträge"
$basepath = "C:\test\new\Data\06. Aufträge"
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 1
ForEach ($Order in $Orders ) {
if ($Order.name.StartsWith("20")){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.insert(6,"_" + $order.parent.Name))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Copy-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -Recurse -Force
#under construction
$MoveFolderName = Join-Path -path $sourcepath -ChildPath $order.parent | Join-Path -ChildPath "Z_Transfered"
if (-not (Test-Path $MoveFolderName))
{
New-Item -Path $MoveFolderName -ItemType "directory"
}
$MoveFolder = $MoveFolderName +"\" + $order.name
Move-Item -Path "$($Order.FullName)\*" -Destination $MoveFolder
$error > $sourcepath"\error.log"
}
}
I adapted the code I got yesterday. Currently I have one more error in the code.
Copy content to the right place works now.
Currently he creates the folder Z_Transfered below the customer folder. The problem seems to be with Move-Item.
Currently, the folder is not moved to Z_Transfered, only the files under the customer folder are moved and, unfortunately, also renamed. Can someone help me here please?
You can get the parentfolder of a folder by putting .parent to the pathobject > $path.parent. And you can even get the grandparent that way > $path.parent.parent.
So all that is left is a little string manipulation to get the new folder name:
$sourcepath = "d:\test\Data\Orders" # Adjust this
$BasePath = "d:\test\Data\Orders" # Adjust this
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 2
ForEach ($Order in $Orders ) {
if ( $Order.parent.parent.Name -eq "Orders" ){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.replace("_","_$($Order.parent)_"))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Move-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -WhatIf
}
}
In Powershell 5 Get-ChildItem got the -Depth parameter so you can limit it to search only two levels below your $sourcepath. The replace will look for _ in the foldername so make sure thery all contain only one.
it works :)
many thanks for your help.
The script works now as I need it.
$sourcepath = "C:\test\old\Data\Werkstatt\06. Aufträge"
$basepath = "C:\test\new\Data\06. Aufträge"
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 1
ForEach ($Order in $Orders ) {
if ($Order.name.StartsWith("20")){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.insert(6,"_" + $order.parent.Name))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Copy-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -Recurse -Force
$MoveFolderName = Join-Path -path $sourcepath -ChildPath $order.parent | Join-Path -ChildPath "Z_Transfered"
if (-not (Test-Path $MoveFolderName))
{
$MoveFolder = New-Item -Path $MoveFolderName -ItemType "directory"
}
Move-Item -path "$($Order.FullName)\" -Destination $MoveFolderName -force
$error > $sourcepath"\error.log"
}
}
I'm targeting simple task.
I would like to create folder of constant name "jpg" in all subfolders of supplied root folder "D:Temp\IMG" and move all files in every subfolder with extension ".jpg" to that newly created "jpg" folder.
I thought I'll be able to solve this by myself without deep knowledge of powershell, but it seems I have to ask.
So far, I created this code
$Directory = dir D:\Temp\IMG\ | ?{$_.PSISContainer};
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.FullName)" -File -Recurse -Filter '*.jpg' |
ForEach-Object {
$Dest = "$($d.DirectoryName)\jpg"
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force}
Move-Item -Path $_.FullName -Destination $Dest
}
}
What I'm getting out of this is infinite loop of folder "jpg" creation in every subfolder.
Where is my code and logic failing here, please?
The following script would do the job.
$RootFolder = "F:\RootFolder"
$SubFolders = Get-ChildItem -Path $RootFolder -Directory
Foreach($SubFolder in $SubFolders)
{
$jpgPath = "$($SubFolder.FullName)\jpg"
New-Item -Path $jpgPath -ItemType Directory -Force
$jpgFiles = Get-ChildItem -Path $SubFolder.FullName -Filter "*.jpg"
Foreach($jpgFile in $jpgFiles)
{
Move-Item -Path $jpgFile.FullName -Destination "$jpgPath\"
}
}
This will accomplish what you are attempting, I'm pretty sure. Your original script doesn't actually recurse, despite specifying that you want it to (Get-ChildItem has some finicky syntax around that), so I fixed that. Also fixed my suggestion (I forgot that the Extension property includes the preceding dot, so 'FileName.jpg' has '.jpg' as the extension). I added in some checking, and have it throw warnings if the file already exists at the destination.
$Directory = dir D:\Temp\IMG\ -Directory
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.fullname)\*" -File -Recurse -filter '*.jpg' |
Where{$_.Directory.Name -ne $_.Extension.TrimStart('.')}|
ForEach-Object {
$Dest = join-path $d.FullName $_.Extension.TrimStart('.')
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force|Out-Null}
If(Test-Path ($FullDest = Join-Path $Dest $_.Name)){
Write-Warning "Filename conflict moving:`n $($_.FullName)`nTo:`n $FullDest"
}Else{
Move-Item -Path $_.FullName -Destination $Dest -Verbose
}
}
}