2

ドライブ間で大量のファイルを頻繁にコピーする必要があり、プロセスが頻繁に開始および停止されます。posixシェルでは、既存のファイルを上書きしないために使用できますが、powershellcp -nには同等の「上書きしない」スイッチがないようです。copy-item

つまり、プロセスを停止して開始する必要がある場合は、使用する必要があります

ls -Recurse|%{
    if (-Not(test-path($_fullname.replace("D:\", "E:\")))){
        cp $_.fullname $_.fullname.replace("D:\", "E:\");
    }
}

test-path問題なく動作しますが、コピーするファイルが 100 万個ある場合、時々起こることですが、毎回実行しなければならないオーバーヘッドが発生すると思います。

編集:ところでrobocopy.exe d:\thedir e:\thedir /XN /XO /S、試してみましたが、すでに存在するファイルをスキャンするのに永遠にかかりました。上記のスクリプトを使用していて、大きなセッションの途中である場合、新しいファイルのコピーを開始する前に数秒の一時停止があります。robocopy を使用すると、コピーを開始する前に、既にコピーされたファイルを実行するのに何分も費やしていました。

4

1 に答える 1

2

別の方法は、宛先が存在する場合に例外をスローするを使用[System.IO.File]::Copy(source,dest)することですが、例外処理とディレクトリの作成のオーバーヘッドに対処する必要があるため、おそらくあまり役​​に立ちません。

.NETExists()メソッドを直接使用して、パス テストで PowerShell のオーバーヘッド (2/3) を削減できます。Exists()-calls を関数にラップしませんでした。これにより、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:\")
    }
}

比較:

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
于 2016-03-12T10:39:28.280 に答える