Got what I thought was a fairly straightforward question but after several hours of Googling I can't find an answer. Pretty sure Powershell is versatile enough to do this, I'm just not sure how to go code it up.
So basically, I have this:
W:\ (root)
Main Folder 1
Subfolder 1
Sub-Subfolder 1
Sub-Subfolder 2
Sub-Subfolder 3
File1.fil
File2.fil
File3.fil
All I'm trying to do is get Powershell to search Subfolder 1 and move Sub-Subfolders 1-3 (and their contents) into Subfolder 1, but ignore Files 1-3.
The syntax that I've worked up looks like this:
$source = "W:\Main Folder 1\Subfolder 1\"
$destination = "W:\Main Folder\"
Get-ChildItem $source -attributes D -Recurse | Move-Item -Destination "$destination" -Force -Verbose
When I -WhatIf it it looks like it should work, but then when I try it I get the dreaded "cannot create a file when that file already exists" (basically it's saying that it can't create folders in Main Folder 1 with the same names as ones from Subfolder 1). I've got a -Force flag there and I'd have thought this would do the trick, but...here we are.
Any idea what to do to force it to move them? (I don't want it to delete the existing folder to move the new one though.)
If I understand what you're trying to do this code works.
$source = "G:\Test\A\FolderTwo"
$destination = "G:\Test\A"
Get-ChildItem -Path $source -Directory |
Move-Item -Destination $destination -Force -Verbose
Verbose Output:
VERBOSE: Performing the operation "Move Directory" on target "Item: G:\Test\A\FolderTwo\Folder2A Destination: G:\Test\A\Folder2A".
VERBOSE: Performing the operation "Move Directory" on target "Item: G:\Test\A\FolderTwo\Folder2B Destination: G:\Test\A\Folder2B".
The 7 regular files in the Source Folder remained there. The Directories in the Source Folder and all their contents including Sub folders were moved.
Just make sure you have the Source & Destination directories defined correctly.
Note there is no need for the -Recurse switch as moving whole directories also moves their contents.
Edited to remove un-necessary quotes per mklelement0's comment below!
This should get you further. Change the "$($folder.name)-2" to whatever you want to append the new folder names with.
$destination = "W:\Main Folder\"
$source = Get-ChildItem "W:\Main Folder 1\Subfolder 1\" -Directory
foreach ($folder in $source) {
$folder | Move-Item -Destination $destination\"$($folder.name)-2"
}
Related
foreach ($file in Get-ChildItem -Path $srcRoot -File -Include "*.pdf" -Force -Recurse {
Above is just a line out of my script that is moving files from one directory to another. Long story short.. My script is working and has been for months. However, today I came across where it didnt move two files that were named like the following.
Thisismyfile.pdf2.pdf
Thisisanotherfile.pdf2.pdf
Now like I said.. the script has been working fine until these files came about. Of course I told the users to make sure they name files correctly ect.. but I dont know why it still didnt move those files. It still contains "*.pdf" as an extenstion.. so what gives?
I suspect that files are not moved in scenario where you have file in folder A with the same name as in folder B. Moving files to the one destination folder will cause name collision with error like Move-Item : Cannot create a file when that file already exists.
If that is the case, please use one of snippets from this answer: Powershell Move-Item Rename If File Exists
I placed few .pdf files (named like a.pdf.pdf, b.pdf.pdf ...) in src directory, running snippet below moves those files to dst folder correctly.
$srcRoot = "C:\Users\$env:username\Desktop\src\"
foreach ($file in Get-ChildItem -Path $srcRoot -File -Include "*.pdf" -Force -Recurse)
{
Move-Item -Path $file -Destination "C:\Users\$env:username\Desktop\dst\"
}
I know this has been asked a million times, but I can't seem to find anything that works for me. I don't know if there is a permissions issue or what, but I am trying to move files from one server to another using a PowerShell script in the task scheduler and it worked for about a week before it stopped working. There are no errors in the task scheduler, and I'm not well versed in PowerShell at all, I'm just trying to get something quick and simple for our CMS manager to move her files from the website to a folder on another server.
$ORG = "E:\folders\uploads\" ## enter current source folder
$DEST= "\\server-folder-structure\uploads\" ## enter your destination folder
foreach ($ORG in gci $DEST -include *.doc,*.docx,*.pdf,*.png,*.gif,*.jpg,*.jpeg,*.html,*.htm -recurse)
{
Move-Item -path $ORG -destination $DEST ## Move the files to the destination folder
}
I tried this too, in hopes it would work, but still no files are being moved.
Get-ChildItem E:\folder-structure\uploads\* -Include *.doc,*.docx,*.pdf,*.png,*.gif,*.jpg,*.jpeg,*.html,*.htm -Recurse |ForEach-Object { Move-Item $_.FullName \\server-folder-structure\uploads\ }
Am I doing something wrong? Are there permissions to folders that I need to set that I don't know about? Is PowerShell just not the best way to do this? Thanks in advance.
I believe you're making this harder than it should be (with respect to PowerShell being new to you). You don't need a loop on any of your examples if you want to pipe directly to Move-Item:
$ORG = "E:\folders\uploads\" ## enter current source folder
$DEST = "\\server-folder-structure\uploads\" ## enter your destination folder
$filterFor = "*.doc","*.docx","*.pdf","*.png","*.gif","*.jpg","*.jpeg","*.html","*.htm"
Get-ChildItem $ORG -Include $filterFor -File -Recurse |
Move-Item -Destination $DEST -WhatIf
As for what you tried, and as Mathias pointed out, you would be searching your $DEST location in which the files wouldn't exist as they would only be in $ORG; given that that's the actual source folder.
This would also overwrite you $ORG variable with the current item in your iteration in: foreach ($ORG in gci ..){ ... }.
Meaning, your Move-Item would be invalid.
It's my first time using a custom Powershell script and I think I might be missing something. Everything works, except it doesn't copy subfolders and their content.
$sourcePath = 'C:\Users\User\Desktop\test\test1'
$destinationPath = 'C:\Users\User\Desktop\test\test2'
$files = Get-ChildItem -Path $sourcePath -Recurse
$filecount = $files.count
$i=0
Foreach ($file in $files) {
$i++
Write-Progress -activity "Moving files..." -status "($i of $filecount) $file" -percentcomplete (($i/$filecount)*100)
# Determine the absolute path of this object's parent container. This is stored as a different attribute on file and folder objects so we use an if block to cater for both
if ($file.psiscontainer) {$sourcefilecontainer = $file.parent} else {$sourcefilecontainer = $file.directory}
# Calculate the path of the parent folder relative to the source folder
$relativepath = $sourcefilecontainer.fullname.SubString($sourcepath.length)
# Copy the object to the appropriate folder within the destination folder
copy-Item $file.fullname ($destinationPath + $relativepath)
}
i'm sure it's something to do with Path instead of Root or the Recurse option that's not used corretly.
If someone could help me it would be really appreciated.
Thank you!
To copy recursively, use
Copy-Item -Path <src> -Destination <dest> -Recurse
See Official documentation.
This may very well work for you.
As for walking through a previously built list of source files and copying one-by-one as you did, it should work. I did not check/debug the code you put together.
If you actually need this walk through, simply debug your code by printing $files and the source and target of your copy-Item, this will tell you the source of problems. Please post this output in the OP.
You may have to use the option -Directory for Get-ChildItem, or class [System.IO.Path].
Hi I have a script that should ideally copy an item and paste it onto a destination folder including all of it's sub folders. However I cannot get it to copy the item into the subfolders.
Here is the code:
Copy-Item "\\postowl\PEC Group\HR\Performance snapshot\Performance Snapshot Macro.xlsm" -Destination "\\postowl\PEC Group\HR\Performance snapshot\2017-2018" -Recurse -Force
Please help!
Recurse copies the subfolders and item from the source to the destination, preserving directory structure. It doesn't recurse in the destination and make multiple copies in the destination. You could use a ForEach-Object loop from the output of Get-ChildItem where you retrieve all of the folders you wish to copy to.
Get-ChildItem "\\postowl\PEC Group\HR\Performance snapshot\2017-2018" -Directory -Recurse | % {
Copy-Item "\\postowl\PEC Group\HR\Performance snapshot\Performance Snapshot Macro.xlsm" -Destination $_.fullname -Force }
Two things from my observation.
1)You are telling you are copying an item including its sub-folders, but in the source you have mentioned one file name with extension. not sure if thats the folder name in your case.
2) I found that in the destination you are not going inside the final level folder.
So put this and check:
Copy-Item "\\postowl\PEC Group\HR\Performance snapshot\*.xlsm" -Destination "\\postowl\PEC Group\HR\Performance snapshot\2017-2018\" -Recurse -Force
Note: If its a specific file, then you can remove the wildcard because that will copy all the files with the extension .xlsm . I have kept it because I am assuming you have only one file under that folder.
See the Documentation and the issue with PS:
Copy-Item Nature & Issue
I would like to use a loop for my program that grabs the file names of only the .dll in the folder and subfolders of that directory. It then searches a specified location/path for a .dll with the same file name and if it exists it replaces it. So far my program copies all files from one location to the other and once they are copied I need the above stated to be worked out.
My biggest issue is how do you search by filenames in a loop at a specified location and if it exists, replace it? Below code is locally in random places before I put the correct paths using servers and other drives.
#sets source user can edit path to be more precise
$source = "C:\Users\Public\Music\Sample Music\*"
#sets destination
$1stdest = "C:\Users\User\Music\Sample Music Location"
#copies source to destination
Get-ChildItem $source -recurse | Copy-Item -destination $1stdest
#takes 1stdest and finds only dlls to variable
#not sure if this is right but it takes the .dlls only, can you do that in the foreach()?
Get-ChildItem $1stdest -recurse -include "*.dll"
Here you go, you'll need to edit your paths back in. Also, note that $1stDest was changed to enumerate the list of files in the destination folder.
The logic goes through all of the files in $source, and looks for a match in $1stDest. if it finds some, it stores them in $OverWriteMe. The code then steps through each file to be overwritten and copies it.
As written, it uses -WhatIf, so you'll have a preview of what would happen before running it. If you like what you see, remove the -WhatIf on line 15.
$source = "c:\temp\stack\source\"
#sets destination
$1stdest = get-childitem C:\temp\stack\Dest -Recurse
#copies source to destination
ForEach ($file in (Get-ChildItem $source -recurse) ){
If ($file.BaseName -in $1stdest.BaseName){
$overwriteMe = $1stdest | Where BaseName -eq $file.BaseName
Write-Output "$($file.baseName) already exists # $($overwriteMe.FullName)"
$overwriteMe | ForEach-Object {
copy-item $file.FullName -Destination $overwriteMe.FullName -WhatIf
#End of ForEach $overwriteme
}
#End Of ForEach $file in ...
}
}
OutPut
1 already exists # C:\temp\stack\Dest\1.txt
What if: Performing the operation "Copy File" on target "Item: C:\temp\stack\source\1.txt Destination: C:\temp\stack\Dest\1.txt".
5 already exists # C:\temp\stack\Dest\5.txt
What if: Performing the operation "Copy File" on target "Item: C:\temp\stack\source\5.txt Destination: C:\temp\stack\Dest\5.txt".