Reputation: 3512
I frequently have to copy large numbers of files between drives, and the process often gets started and stopped. In a posix shell I can use cp -n
to not overwrite existing files, but there doesn't seem to be an equivalent "do not overwrite" switch for copy-item
in powershell.
What that means is that if I have to stop and start the process I have to use
ls -Recurse|%{
if (-Not(test-path($_fullname.replace("D:\", "E:\")))){
cp $_.fullname $_.fullname.replace("D:\", "E:\");
}
}
Works fine, but if I have a million files to copy, as sometimes happens, I'd imagine there's going to be some overhead having to execute test-path
every time.
EDIT: BTW I tried robocopy.exe d:\thedir e:\thedir /XN /XO /S
, but it took forever to scan for files that were already there. If I use the script above and I'm half way through a big session, there will be a few seconds pause before it starts copying new files; with robocopy it was spending minutes running through the already copied files, before it even started copying.
Upvotes: 2
Views: 2384
Reputation: 54881
The alternative is to use [System.IO.File]::Copy(source,dest)
which will throw an exception when the destionation exists, but then you have to deal with the overhead of exception-handling + creating directories, so it problably won't help much.
You can use the .NET Exists()
methods directly to cut away some powershell-overhead (2/3) on the path-testing. I did not wrap the Exists()
-calls in a function as that adds powershell-overhead.
#Avoid aliases in scripts. You want people to be able to read it later
Get-ChildItem -Recurse| ForEach-Object {
if (-Not([System.IO.File]::Exists($_fullname.replace("D:\", "E:\")) -or [System.IO.Directory]::Exists($_fullname.replace("D:\", "E:\")))){
Copy-Item -Path $_.fullname -Destination $_.fullname.replace("D:\", "E:\")
}
}
Comparison:
Measure-Command { 1..100000 | % { [System.IO.File]::Exists("C:\users\frode") -or [System.IO.Directory]::Exists("C:\users\frode") } } | Select-Object -ExpandProperty totalseconds
6,7130002
Measure-Command { 1..100000 | % { Test-Path "C:\users\frode" } } | Select-Object -ExpandProperty totalseconds
22,4492812
Upvotes: 2