I want to copy a folder, complete with subdirectories, files and files within subdirectories, preserving the structure and create them in a new location that did not previously exist. This is my PowerShell code
Copy-Item c:\development\powershell\folderone\* c:\development\powershell\foldertwo -recurse -Container
Copy-Item c:\development\powershell\folderone\* c:\development\powershell\folderthree -recurse -Container
foldertwo exists and is empty, folderthree does not exist.
If I run the script, the structure is created correctly in foldertwo, however folderthree gets created, but contains only all the files from the entire substructure, all at the root folderthree level. It has not recreated the subfolders within folderone, just put all the files at the root level of folderthree.
What have I done wrong?
Here's a very basic, but fully working and tested example, building on your confirmation above that I understood the issue at-hand:
$folderlist = ("foldertwo", "folderthree")
foreach ($folder in $folderlist)
{
if (!(Test-Path "C:\Development\PowerShell\$folder"))
{
mkdir ("C:\Development\PowerShell\$folder") | Out-Null
}
Copy-Item c:\development\powershell\folderone\* c:\development\powershell\$folder -recurse -Container
}
From what I understand, the question is about recreating the folder structure from [source] to [destination]. As using CmdLets is kind of overkill (and performance loss), I suggest simple batch command that may also be ran in powershell.
xcopy [source] [destination] /T /E
xcopy is a function to copy file and directory trees.
Help provides us info on usefult parameters on the case:
/T Creates directory structure, but does not copy files. Does not
include empty directories or subdirectories. /T /E includes
/E Copies directories and subdirectories, including empty ones.
Same as /S /E. May be used to modify /T.
Related
I am trying to copy music lyric files (.lrc) from a folder with many subfolders such as artists and albums and paste them in an empty folder, but I still want to keep the folder structure without having to create each individual folder for those files to be put in. In other words: I want to take certain files from a folder and have it automatically create the folder structure in another folder which the original file was in.
For example: I have 10 lyric files accompanied with other music files in a single folder called "ArtistName" which is a subfolder of a subfolder of a folder called "Music". These lyric files need to be in another folder called "Music2" that is currently empty, but instead of just dumping the files in the root folder, I need to recreate the folder structure in which the original lyric files were in.
Is there any way to do this? Keep in mind, I am not very experienced when it comes to programming but I know some basics. Unfortunately I might need more of an explanation than most people here. Thank you to anyone who can help!
Here's a powershell answer:
Use Copy-Item with the -Container and -Recurse switches to copy the folder structure including files to a new location.
Copy-Item -Path "Old\Path\for\Music" -Recurse -Destination "New\Path\for\Music" -Container
If you only want to copy the lyric files while retaining the folder structure use a -Filter
Copy-Item -Path "Old\Path\for\Music" -Recurse -Filter "*.lrc" -Destination "New\Path\for\Music" -Container
You can do this in CMD
xcopy /s yourFolder\Subfolder\*.pdf destinationFolder\myfolder
powershell, recurse option keeps the folder structure
copy-item c:\\srcFolders\\* f:\\dst -force -recurse -verbose
I have requirement as below.
Source : C:\s
Destination: C:\d
files located are more than 255 characters.
Moving files based on last modified or written days(10) and it should copy complete folder structure, if any of the files not modified as per the last modified date it should be available at the source file in the same folder. While the other is modified, it should be created with a new directory with the same folder structure and file to moved in the same location as per the source location path.
I have tried PowerShell script using days, however the files are being copied into and folders are staying at the source itself.
Get-ChildItem -Path C:\s -Recurse | Where-Object {$_.LastWriteTime -lt (Get-date).AddDays(0)} | Move-Item -destination C:\d
So far the output is giving only files but not the folder structure, if it is empty folder it should be moved to the destination folder.
Thanks
Suman
The issue is that you are getting all the files with Get-ChildItem -Recurse and filtering them, but when those files are piped to Move-Item -Destination you essentially are saying to take all files (regardless of the source) and put them into the single folder C:\d. If you want to preserve the directory structure, you have to pass through and specify the directory structure in the Move-Item -Destination parameter.
#AdminOfThings is correct, an easier way to do the move is to use Robocopy. Experimenting with the various switches should get you what you need. e.g.:
Robocopy.exe C:\s C:\d /move /e /minage:10
Where:
/move says to move instead of copy
/e is copy directories including empty ones
/minage:10 is to move files older than 10 days.
I have a set of projects that involve a mix of project-specific files plus common files. I'm trying to copy contents from two different folders -- a project-specific folder, and a common folder -- into a single folder named for the project. I also want to retain any folder hierarchies from the original folders.
For example, some paths to the common files:
src\Common\PackageAssets\logo1.jpg
src\Common\PackageAssets\logo2.jpg
And example paths to project-specific files:
src\Projects\ProjectA\PackageFiles\readme.txt
src\Projects\ProjectA\PackageFiles\scale-100\projA.png
The desired result after copying would be:
bld\ProjectA\pkgFiles\logo1.png
bld\ProjectA\pkgFiles\logo2.png
bld\ProjectA\pkgFiles\readme.txt
bld\ProjectA\pkgFiles\scale-100\projA.png
What I'm using is this:
[string]$pkgContentPath = "bld\$project\pkgFiles"
# copy common files
Copy-Item -Path .\src\Common\PackageAssets -Recurse -Destination $pkgContentPath
# copy project-specific files
Copy-Item -Path .\src\Projects\ProjectA\PackageFiles\ -Recurse -Destination $pkgContentPath
But instead of the expected results, all the files are ending up in an extra level of subfolder:
bld\ProjectA\pkgFiles\PackageAssets\logo1.png
bld\ProjectA\pkgFiles\PackageAssets\logo2.png
bld\ProjectA\pkgFiles\PackageFiles\readme.txt
bld\ProjectA\pkgFiles\PackageFiles\scale-100\projA.png
I'm stumped. I can't figure out how to get rid of the extra subfolder layer. I tried using Get-ChildItem piping to Copy-Item, but then the subfolder hierarchies were lost.
In a .bat file, this works:
xcopy src\Common\PackageAssets\* bld\%project\pkg_contents /s
xcopy src\Projects\%project\PackageFiles bld\%project\pkg_contents /s
I guess I could use xcopy, but surely there must be a way to do this using cmdlets.
The behavior you describe is a known problem as of Windows PowerShell v5.1 / PowerShell Core v6.2.0-preview.2, unfortunately:
In short, the behavior of Copy-Item regrettably depends on whether the target directory happens to exist already or not:
If the target dir. exists, it is not the source directory's content that is copied, but the source dir. as a whole, to a subdirectory of the target directory named for the source dir.
The workaround is already mostly spelled out in PetSerAl's helpful comment on the question:
Before copying, make sure that the target directory exists.
Append \* to the source path to explicitly target the contents of the source dir.
Also specify -Force, so as to ensure that hidden files and directories are also copied.
$pkgContentPath = "bld\$project\pkg_contents"
# Make sure the target dir. exists.
# (-Force leaves an existing dir alone and otherwise creates it.)
New-Item -Force -Type Directory $pkgContentPath
# IF desired, clear out the pre-existing directory content.
# !! Beware of Remove-Item's intermittent failures - see below.
# Remove-Item -Force $pkgContentPath\* -Recurse.
# Copy with \* appended to the source paths and -Force added:
#
# copy common files
Copy-Item -Recurse -Force -Path .\src\Common\PackageAssets\* $pkgContentPath
# copy project-specific files
Copy-Item -Recurse -Force -Path .\src\Projects\ProjectA\PackageFiles\* $pkgContentPath
A note re use of Remove-Item -Recurse to clear out preexisting destination-directory content, if needed: Regrettably, Remove-Item can fail on occasion and you cannot predict when that happens - see this answer for a robust alternative.
I have a powershell script that works as such: it deletes any files or folders within C:\users\%user1,2,3...etc%\temp. It goes through each user in users folder and finds if it has a temp folder then deletes stuff inside.
I need to know whats the best way to have this be done in Batch to avoid compatibility issues?
$users = Get-ChildItem C:\Users
foreach ($user in $users){
$folder = "$($user.fullname)\AppData\Local\temp"
If (Test-Path $folder) {
Get-ChildItem -Path $folder -Include * | remove-Item -recurse
}
}
You can do the following in a batch file to loop through C:\USERS and remove items in the TEMP folder:
for /d %%F in (c:\users\*) do del "%%F\appdata\local\temp\*" /s /q
If you run this at a command line, use just one percent sign, when using it a batch file, use two percent signs.
This command loops over all directories in C:\USERS, and then runs a DEL against the AppData\Local\Temp folder, using silent and recursive parameters. This assumes that your user profiles are stored in C:\USERS, if you have reason to need to look for profiles everywhere, you'll want to adjust your batch file to find the profile paths from the registry first.
As with all code you find online, test before running in production.
I was asked to benchmark using a powershell script to do some basic file copying as opposed to using XCopy in a batch file. It seems to run in roughly about the same amount of time, but with Powershell the parent folder of the tree structure is not being created in the destination, whereas with XCopy the parent folder does get created. For example, with
xcopy D:\Webs\First\*.* D:\Test\Sandbox\ /E
The "First" folder does get created with all its contents. Whereas with
$SourceFolder = "D:\\Webs\\First\\"
$TargetFolder = "D:\\Test\\Sandbox\\"
Copy-Item $SourceFolder $TargetFolder -recurse
The folder named "First" does not get created and rather the contents are copied to the destination. If I use "Webs" as the source folder, there are other folders at the same level as "First" that get copied as well and that is not desirable.
How do I get the Parent folder "First" to copy to the destination using the Copy-Item or some other powershell command without manually creating this folder within the script so I get the exact same results?
Thanks...
for a quick way you can append the source parent folder before copy, e.g.
$TargetFolder = "D:\\Test\\Sandbox\\"+($SourceFolder | Split-Path -leaf)
you can also use the Measure-Command Cmdlet for timings