I need to be able to copy all items within a drive and move them to a new destination using Powershell. At present, I've tried doing this with Copy-Item but am unable to do so within a drive. I've looked for solutions elsewhere but have yet to find a working fix, Any suggestions?
Copy-Item -Path 'P:' -Destination 'Destination'
If you're trying just to copy all of the items from one drive to a folder on another drive, you can use Copy-Item, like you are, with a few adjustments (-Destination path is just an example):
Copy-Item -Path C:\* -Destination F:\destinationPath -Recurse
Using the * in C:\* for the path tells the shell to get all files and directories at that folder, in this case, the C: root. -Recurse tells it to copy all files and directories recursively. Consider adding the -Force parameter if you want to use this in automation, as it will forcibly overwrite any existing files at the destination rather than prompt for input.
Related
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 wanted to update an app.
In order to do this, i want to test if files AND folders from $path_new exists in $path_old. If so, delete those from $path_old and copy those from $path_new, if not, keep them on $path_old.
So, i'll keep everything except updated files.
Edit : Using PowerShell.
Edit : So if an user added a personnal folder in the app mmain folder, he'll keep it.
Maybe i'll look like this :
$FileName = "C:\Share\test.txt"
if (Test-Path $FileName)
{
Remove-Item $FileName
}
But it's not exactly what i want. I think i'll have to add a "for" loop, but how, where ?
This will copy files from the source directory to the target directory. 'Personal files', or files not existant in the source directory, will be ignored while files that exist in both folders are overwritten.
In addition to that, I'd like to point out that your approach to this problem is inefficient so to speak. It's a lot more work to search for files existing in both directories, deleting those, and then copying those over from the new directory to the old directory. Instead you should just use existing file copy actions such as Copy-Item as they have built-in functionality to overwrite existing files.
$target = ".\old"
$source = ".\new"
Get-ChildItem -Path $source | Copy-Item -Destination $target -Recurse -Force -Container
Parameters
-Recurse Copy all files and folders recursively.
-Force Copy items that cannot otherwise be changed, such as copying over a read-only file or alias.
-Container This will retain the folder structure when doing recursive copy actions.
I want to copy a group of folders which have various files inside them from one place to a single folder elsewhere. I want to bind said folder group to a variable.
param(
$folders=('../folder1','../folder2')
)
Copy-Item -Path $folders -Destination '../folder3' -Recurse -Force;
This works, however, inside folder3, folder1's contents are spilled out, while folder2's contents are placed in a folder of the same name just like intended.
I need them both to be copied intact, if I switch their places then folder2 gets the same treatment. It's like the script does not read the first folder in line in same way as the others. Am I missing something?
EDIT:
Managed to find a work-around by running additional command to create a folder inside "folder3" named same as first in line folder before copying. Script then places the files inside that folder correctly. Still rather messy, I wonder if it's a bug.
Use a loop
foreach($folder in $folders){
Copy-Item -Path $folder -Destination '../folder3'-Recurse -Force
}
I'm having a few issues while copying desktop files as a part of the back up process from local folder to server.
My script automatically creates a backup folder on the server and I just realised when it creates the back up folder windows automatically creates a desktop.ini file, and as desktop.ini is a system file the script failed to write another desktop.ini from desktop to the backup folder in server.
My initial code was :
Copy-Item ("$Global:localBackupRestoreLocation\Desktop\$file") ("$Global:remoteBackupRestorePath\$nameOfbackupDirectory") ($recursive="true")
But I was to use the exclude in that line and I know exclude does not work recursively and I have to use Get-ChildItem.
Try something like this
$Exclude = #('desktop.ini')
copy-item -Path $Source -Destination $Dest -Exclude $Exclude
I know how to do it with different commands but is there a way to make it so copy-item cmdlet also copies directories to the target folder for example if I wanted to copy everything in the C:\users folder including all directories and sub directories is it possible to do with the copy-item command.
You should be able to do it with:
copy-item C:\users -recurse
copy-item C:\users -destination c:\somewhereelse -recurse
The first way assumes you are currently in the destination folder, the second way is explicit.