PowerShell の Copy-Item Cmdlet とは?
Powershell の Copy-Item cmdlet は、主にソースから宛先へファイルをコピーするために使用されます。コピーするファイルは、個別のファイルであっても、内容を含む複数のファイルであっても可能です。ローカルやネットワーク共有など、さまざまなファイルシステム間でも動作できます。
基本的な構文とパラメーター
PowerShell の Copy-Item cmdlet の基本的な構文は次のとおりです。
Copy-Item -Path <source> -Destination <destination> [<parameters>]
cmdlet だけを入力すると、PowerShell は下のように Source の入力を求めます。
初心者向け Windows PowerShell スクリプト入門(PDF)
詳しく見る最初の必須パラメーターはソース パスです。この項目パス パラメーターは、コピーする項目(または項目群)へのパスを指定します。ソースはファイル パスまたはフォルダー パスにできます。複数のパスはカンマ区切りのリストを使って指定でき、パスにはワイルドカードを含めることも可能です。ベストプラクティスとして、項目をコピーする先のパスを指定するために宛先パス文字列を用意することをおすすめします。単一の項目をコピーする場合は、必要に応じて、パスにコピー後の項目の新しい名前を含めることもできます。
以下は Copy-Item PowerShell cmdlet のその他のパラメーター一覧です:
- -Recurse: サブディレクトリとその内容を再帰的にコピーします。つまり、Copy-Item cmdlet は最上位フォルダーと、その下にあるすべての階層のサブフォルダーに適用されます。
- -Force parameter: 既存の読み取り専用ファイルを上書きし、宛先ディレクトリが存在しない場合は作成します。
- -Container: コピー操作中にコンテナー オブジェクトを保持します。ディレクトリ構造をコピーする場合に役立ちます。
- -Filter: path パラメーターを絞り込むためのフィルター文字列を指定します。たとえば、特定のファイル拡張子を指定できます。
- -Include: コピーする項目を指定し、ワイルドカードをサポートします。Path と Include の両方のパラメーターに一致する項目のみがコピーされます
- -Exclude: コピーから除外する項目を指定し、ワイルドカードをサポートします
- -Credential: 操作に使用するユーザー アカウントの資格情報を指定します
- -WhatIf: コマンドを実行せずに、実行した場合に何が起こるかを表示します
- -Confirm: コマンドを実行する前に確認を求めます
- -FromSession: リモート ファイルを取得する元となる PSSession オブジェクトを指定します。
- -ToSession: リモート ファイルを送信する先の PSSession オブジェクトを指定します
厳選した関連コンテンツ:
よくある使用例
ほとんどの例では、ファイルをローカル コンピューター上の複数の場所にコピーします。ただし、Copy-Item コマンドレットには、次のようにさまざまなよくある使用例があります。
- 重要なファイルやフォルダーのバックアップを作成する
- ファイルや簡単なアプリケーションを複数のマシンに配布する
- サーバーまたはストレージ間で大量のファイルを移行する
- 開発者は開発のさまざまな段階において、プロジェクトフォルダーのスナップショットを作成できます。
- 設定ファイルを複数のサーバーに分散して配布する
それでは、Copy-Item の cmdlet を他のファイル管理 cmdlet と比較してみましょう:
Copy-Item と Move-Item の違い:
- Copy-Item は重複(複製)を作成し、元のものはそのまま残します
- Move-Item はファイル/フォルダーを別の場所に移動し、元の場所から削除します
Copy-Item と Get-ChildItem の違い
- Copy-Item はコピー処理を実行します
- Get-ChildItem はファイルとフォルダーを一覧表示し、多くの場合 Copy-Item と組み合わせて使用されます
基本的なファイルコピーには、Copy-Item cmdlet を推奨します。大きなファイルの転送やミラーリングのために、より高度な機能を求める場合は Microsoft Robocopy を検討してください。
Copy-Item PowerShell Cmdlet を使ったファイルのコピー
基本的なファイルコピーの例
この例では、PowerShell の copy item コマンドを使って、スプレッドシートをあるフォルダーから別のフォルダーへコピーします。
Copy-Item -Path "C:\Destination One\SpreadsheetOne.xlsx" -Destination "c:\Destination Two"
PowerShell では次のようになります:
複数のファイルをコピーする
次は、一度に複数のファイルをコピーしましょう。ファイル パスは別々のドライブを使用している点に注意してください。なお、宛先のディレクトリが存在しない場合は、PowerShell がそれを作成します。
Copy-Item -Path "C:\source\file1.txt","C:\Source\file2.txt" -Destination "D:\Destination Two"
名前を変更してファイルをコピーする
以下のコマンドを使うことで、ファイルを新しいフォルダーにコピーし、その過程で名前も変更できます。
Copy-Item -Path "C:\Source\file1.txt" -Destination "C:\Destination Two\NewName1.txt"
PowerShell では次のようになります:
PowerShell でフォルダーをコピーする
PowerShell のコピー機能はファイルに限りません。Copy-Item コマンドレットを使って、フォルダーを新しい場所にコピーすることもできます。以下では、PowerShell の「フォルダーとその内容をコピーする」コマンドの使い方を示します。
基本的なフォルダーのコピー例
以下の PowerShell のコピー フォルダー コマンドを使用して、フォルダーを別の場所にコピーします。この PowerShell のコピー コマンドは、「source」フォルダー内のすべてのファイルをコピーし、宛先フォルダーに配置します。
Copy-Item -Path "C:\source\folder" -Destination "D:\destination"
サブフォルダー付きフォルダーのコピー
ソース フォルダーの中に複数のサブディレクトリが含まれていたらどうなるでしょうか。上記の基本コマンドを使用すると、サブフォルダー内の内容はすべて無視されてしまいます。サブディレクトリの内容を含めて、ソース フォルダー内のすべてをコピーしたい場合は、Recurse パラメーターを使用して PowerShell のフォルダーとサブフォルダーのコピー コマンドを実行する必要があります。
Copy-Item -Path "C:\source\folder" -Destination "D:\destination" -Recurse
厳選された関連コンテンツ:
複数フォルダーのコピーとマージ
たとえば、2つのソース フォルダーにあるファイルをコピーし、それらを1つの宛先フォルダーに統合したいとします。これは、PowerShell の「copy contents of folder to another folder」コマンドを使えば簡単に実現できます。ここでは、2つのソース パスがカンマで区切られています。まずそれらがコピーされ、その後、宛先フォルダーに統合されます。
Copy-Item -Path "C:\source1\*","C:\source2\*" -Destination "D:\destination"
高度なファイルおよびフォルダーのコピー手法
ファイル パスでワイルドカードを使用する
ワイルドカードを使うと、各項目を個別に列挙しなくても、特定のパターンに一致する複数のファイルまたはフォルダーをコピーできます。ワイルドカードを使用すれば必要なコード量を大幅に減らせるため、ファイルやフォルダーの数が多い場合の処理に最適です。下の例では、ワイルドカードがあらゆる .txt ファイルに対して使われています:
Copy-Item -Path "C:\source\*.txt" -Destination "C:\Destination Two"
PowerShell では次のようになります:
Include パラメーターと Exclude パラメーターでファイルをフィルタリングする
フォルダー内の特定のファイルを、コピー対象から除外したい場面があります。特定のファイル形式やファイル バージョンだけを含めたい場合や、機密情報を含む特定のファイルは含めたくない場合もあるでしょう。そのため、バックアップや移行の手順では、一時ファイルや不要なファイルを除外したくなるはずです。
次の例では、すべてのログ ファイルをコピー対象として扱うよう指定してコピーします。ただし、.tmp 拡張子も持つログ ファイルは除外されます。
Copy-Item -Path "C:\source\*" -Destination "D:\destination" -Include "*.log" -Exclude "*.tmp"
Force パラメーターを使ってファイルを上書きする
既定では、Copy-Item は確認なしで、宛先にある既存のファイルを上書きします。場合によっては、宛先フォルダーに、コピーしようとしているファイルと同じ名前の読み取り専用ファイルが含まれていることに遭遇するかもしれません。既定では、Copy-Item はこの読み取り専用ファイルを上書きしません。しかし、-Force パラメーターを使ってこの動作を上書きし、上書きを強制することができます。使い方の例は次のとおりです:
Copy-Item -Path "C:\source\file.txt" -Destination "D:\destination" -Force
Copy-Item を使用してリモート コンピューターにファイルとフォルダーをコピー
ローカル コンピューターで、ファイルやフォルダーを別のドライブ位置にコピーする必要が生じる状況もありますが、Copy-Item cmdlet の真の強みは、リモート コンピューター間でファイルやフォルダーを転送できるようにする点にあります。
New-PSSession でリモート セッションをセットアップ
たとえば、PowerShell を使っていくつかのファイルをリモート コンピューターにコピーしたいとします。ローカルの管理者権限を持っている場合でも、現在のアカウントに、宛先コンピューターへの適切な権限がない可能性があります。また、リモート マシンのコンピューター名(computername)を把握しておく必要があります。この場合、別の資格情報(alternative credential)を使って、新しいコンピューターとリモート セッションを確立しなければなりません。以下の $session コマンドを使用して、PowerShell でファイルをフォルダーにコピーできます。
$session = New-PSSession -ComputerName "RemotePC" -Credential "User"
リモート コンピューターにファイルをコピーする
これで、確立されたセッションを使ってリモート コンピューターにファイルをコピーできるようになりました。
Copy-Item -Path "C:\source\file.txt" -Destination "C:\remote\destination" -ToSession $session
リモート コンピューターからファイルをコピーする
もちろん、リモート コンピューターからローカル コンピューターへファイルをコピーしたい場合もあります。その場合は、次のコマンドを使用してください。
Copy-Item -Path "C:\remote\source\file.txt" -Destination "C:\local\destination" -FromSession $session
リモート フォルダーを再帰的にコピーする
前の例(リモート コンピューターに関する例)では、サブフォルダーとその内容はコピー操作に含まれていませんでした。ソース項目パスの全内容(すべてのサブフォルダーとファイルを含む)を含めるには、ローカルのコピー操作で行ったのと同様に、Copy-Item コマンドに -Recurse パラメーターを追加してください。
Copy-Item -Path "C:\remote\source\folder" -Destination "C:\local\destination" -FromSession $session -Recurse
厳選した関連コンテンツ:
エラー処理と検証
WhatIf パラメーターと Confirm パラメーターの使用
WhatIf パラメーターを使用すると、変更を加えることなくコマンドの結果を検証できます。たとえば、下の例のように、コピー処理を実行する前に、ソースと宛先のパスが正しいことを確認したい場合があります。
上書き(overwrite)される動作も確認できます。これにより、宛先でどのファイルが上書きされるかが分かり、意図しないデータ損失を避けるのに役立ちます。WhatIf は、どの項目が正確にコピーされるのかを理解するのに役立ちます。コマンドのパラメーターは以下のとおりです。
Copy-Item -Path "C:\Source\File1.txt" -Destination "C:\Destination Two" -WhatIf
デフォルトでは、ほとんどの PowerShell cmdlet は、ユーザーの確認なしにシステムへ変更を加えます。実行される操作について、ユーザーに確認させたい場合があるかもしれません。最も良い例は、PowerShell を使ってファイルを削除するケースです。以下の例では、confirm コマンドを使用してユーザーに確認を求めます。
Remove-Item -Path C:\file.txt -Confirm
下記のとおり、そのコマンドは PowerShell で実行されます。
任意の Copy-Item コマンドに -Confirm パラメーターを追加できます。
コピー処理の確認
PowerShell を使って重要なファイルをバックアップする場合、コピー処理が実際に行われたかどうかを確認したいことがあります。以下のような簡単な PowerShell スクリプトを作成し、ファイル数・サイズ・タイムスタンプを比較することで、ファイルのコピーが行われたことを確認できます。
# Define source and destination paths
$source = "C:\SourceFolder"
$destination = "C:\DestinationFolder"
# Copy the files from source to destination
Copy-Item -Path $source\* -Destination $destination -Recurse
# Confirm the files were copied by checking if they exist in the destination folder
$sourceFiles = Get-ChildItem -Path $source
$allCopied = $true
foreach ($file in $sourceFiles) {
$destinationFile = Join-Path $destination $file.Name
if (Test-Path $destinationFile) {
Write-Host "File '$($file.Name)' was copied successfully."
} else {
Write-Host "File '$($file.Name)' failed to copy."
$allCopied = $false
}
}
if ($allCopied) {
Write-Host "All files copied successfully."
} else {
Write-Host "Some files failed to copy."
}
エラーの処理とリトライ
大きなファイルのコピーを行う場合、スクリプトが正しく動作し、予期しない障害が発生しても復旧できるようにするため、エラー処理を活用するとよいでしょう。PowerShell でエラーを処理する主な方法は、try-catch ブロックです。以下のスクリプトでは、ファイルのコピー中に発生したエラーを処理するために try-catch を使用しています。
# Define source and destination paths
$source = "C:\SourceFolder"
$destination = "C:\DestinationFolder"
# Function to copy files with error handling
function Copy-Files {
try {
# Copy files and set error action to stop failure
Copy-Item -Path $source\* -Destination $destination -Recurse -ErrorAction Stop
Write-Host "Files copied successfully."
}
catch {
# Log the error message
Write-Error "An error occurred while copying files: $($_.Exception.Message)"
# Perform additional actions, like retrying or logging
}
finally {
Write-Host "Copy operation complete."
}
}
# Execute the function
Copy-Files
Copy-Item コマンドレットの実用的な例とユースケース
よくある作業の詳細な例
- 故障しつつあるハードドライブからファイルをコピー: ハードドライブに故障の兆候が見られ、ドライブが故障する前に重要なファイルを安全な場所へコピーする必要があります。
- 毎日のファイル変更に対応するバックアップ自動化: 災害復旧のために、企業は重要なディレクトリ内のすべてのファイルをバックアップサーバーにバックアップする必要がある場合があります。
- オンプレミス サーバーからクラウド ストレージへの移行: 企業は、ローカル サーバーのドキュメントをローカル ドライブから、Azure や AWS などのクラウド ストレージ プロバイダーへ移行したい場合があります。
- 複数のサーバーに構成ファイルを展開する: システム管理者は
C:\ConfigUpdatesから一連のリモート サーバーへ更新された構成ファイルを展開したいと考えています。
実際のシナリオと解決策
複雑なファイル構造は、Copy-Item cmdlet を使用する際にいくつかの難しいケースを引き起こすことがあります。たとえば、260 文字を超えるファイル パスをサポートしていない古い Windows バージョンでは、長いファイル パスが問題になる可能性があります。そのような場合は、ローカルのファイル パスではなく UNC パスを使用するとよいでしょう。
Copy-Item の cmdlet で -LiteralPath パラメーターを使用する必要が出る場合があります。これは、パスに特殊文字(例: [, ]、または *)が含まれていて、PowerShell がそれらをワイルドカード文字やエスケープシーケンスとして解釈してしまう可能性がある場合に必要になることがあります。
権限の問題もよくあるケースです。-Force パラメーターを使用して一部の制限を上書きすることもできますし、PowerShell を管理者として実行することもできます。
厳選した関連コンテンツ:
自動化用のサンプル スクリプト
できるだけ多くの手作業を自動化して業務を効率化し、人為的なミスを防ぐことは、あなたにとって有益です。以下は、フォルダーをバックアップ ディレクトリにバックアップするために使用する PowerShell スクリプトの例です。
# Define source and destination directories
$sourcePath = "C:\SourceDirectory"
$backupPath = "D:\BackupDirectory"
# Get current timestamp to append to the backup folder
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
# Create a new folder for the current backup with timestamp
$backupDestination = "$backupPath\Backup_$timestamp"
New-Item -ItemType Directory -Path $backupDestination
# Copy all files and directories from the source to the backup folder
try {
Copy-Item -Path $sourcePath -Destination $backupDestination -Recurse -Force
Write-Output "Backup completed successfully on $(Get-Date)"
} catch {
Write-Output "An error occurred during the backup: $_"
}
# Optional: Clean up old backups (e.g., delete backups older than 30 days)
$daysToKeep = 30
$oldBackups = Get-ChildItem -Path $backupPath -Directory | Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$daysToKeep) }
foreach ($backup in $oldBackups) {
try {
Remove-Item -Path $backup.FullName -Recurse -Force
Write-Output "Old backup removed: $($backup.FullName)"
} catch {
Write-Output "An error occurred while deleting old backups: $_"
}
}
ヒントとベストプラクティス
Copy-Item の使用に関するベストプラクティス
Copy-Item の cmdlet はシンプルですが、より複雑な状況で役立つ可能性のあるベストプラクティスをいくつか紹介します。
- PowerShell を管理者として実行
- ディレクトリ構造全体をコピーするには、-Recurse パラメーターを使用します。
- 意図しない上書きを防ぐために、-Force パラメーターは慎重に使用してください
- 大規模なディレクトリをコピーする場合は、Robocopy などの代替手段や、大きなジョブにより適した別のツールの使用を検討してください。
- 実際の変更を行わずに何が起こり得るかを確認するために、コマンドのテストでは -WhatIf の使用を検討してください。
よくある落とし穴と回避方法
ベストプラクティスに加えて、PowerShell スクリプトを使用する際は、次のようなよくある落とし穴にも注意してください:
- 想定どおりに解決されない誤ったパスや相対パスの使用は避けるために、フルパスを使用してください。
- 基になるサブディレクトリをつい見落としがちなので、-Recurse パラメーターを使用して、親ディレクトリに含まれるすべてのファイルがコピーされるようにしてください。
- 権限が不十分だと、コピー操作を完了できません。特にリモート マシンが関係する場合は、なおさらです。適切な権限を確認し、必要に応じて昇格(elevated privileges)を使用してください。
- 複雑なコピー処理が正しく完了しない場合は、try-catch ブロックを使用し、適切なエラーログを実装してください。
パフォーマンスに関する考慮事項と最適化
大量のデータセットをコピーすると、コンピューター上で多くの処理能力が消費される可能性があります。並列処理(Parallel processing)は、タスクをより小さな部分に分割し、複数のプロセッサまたはコア上で同時に実行することで処理する計算技術です。Copy-Item cmdlet のようなファイル操作に適用すると、並列処理によりパフォーマンスが大きく向上することがあります。ファイルを1つずつ順番にコピーする代わりに、並列処理では複数のファイルを同時にコピーでき、最新のマルチコアプロセッサの総合的な処理能力を活用します。このアプローチにより、利用可能なシステムリソースをより効率的に使えるため、大規模なコピー処理に必要な時間を大幅に短縮できます。Copy-Item cmdlet は並列処理をネイティブにサポートしていませんが、PowerShell には ForEach-Object -Parallel のようなメカニズムが用意されており、Copy-Item と組み合わせて並列ファイルコピーを実現できます。これは、多数のファイルや複雑なディレクトリ階層が関係するシナリオで、かなりのパフォーマンス向上につながる可能性があります。基本的な例は以下のとおりです:
<$sourcePath = "C:\SourceFolder"
$destPath = "D:\DestinationFolder"
Get-ChildItem $sourcePath | ForEach-Object -Parallel {
Copy-Item $_.FullName -Destination $using:destPath -Force
} -ThrottleLimit 8
結論
Copy-Item cmdlet コマンドは、ファイルやディレクトリ操作を管理するための PowerShell の汎用的なツールです。コピー対象の項目パスを指定したり、エラー処理を実装したりする機能など、さまざまな状況をカバーするための多様なパラメーターが用意されています。ソースから宛先へファイルをコピーするために PowerShell スクリプトを使う場合でも、ローカルまたはリモートのシステム間でファイルをコピーする場合でも、Copy-Item cmdlet は重要なコピー機能を効率よく実行できます。大規模で複雑なデータセットのパフォーマンスを高めるために並列処理を導入することを検討するか、大量のデータ転送を処理するように設計された専用ツールを調べてみてください。Copy-Item cmdlet を使いこなすことで、正確なファイル転送を実現でき、あらゆる PowerShell ユーザーのツールキットにとって不可欠な要素になります。一方で、その制限を理解しておくことで、代替手法をいつ採用すべきかについて情報に基づいた判断が可能になります。
共有する
もっと詳しく
著者について
Kevin Horvatin
リード ソフトウェア アーキテクト
Kevin Horvatin は Netwrix のリード ソフトウェア アーキテクトであり、Netwrix Privilege Secure を担当しています。20 年以上のソフトウェア開発経験があり、PowerShell と C# が登場して以来、それらを扱ってきました。