はじめに
どうも、ATLのヴィリアスです。
最近、社内でとあるフォルダの整理をしました。
そのときに「とりあえず整理前フォルダのバックアップを取っておこう」ということで、
何も考えずにPowerShellでCopy-Itemをしたら「????」な問題が発生してしまいました。
問題を解決するまで少し悩んでしまったので、今後忘れないように記事にすることにします。
※免責事項(必ず、ご一読ください)
記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
必ずしも正確性を保証するものではありません。ご了承ください。
やろうとしたこと
とあるフォルダの構成を、そのフォルダ内にバックアップフォルダを作成し、そこにPowerShellでまるごとコピーする。
具体的に
サンプルとして、~\Qiita\Copy-Item\フォルダ
にA, B, Cの3フォルダが存在するとします。
今回の記事では、このフォルダ構成のバックアップを取っていきます。
ちなみに、A, B, Cのフォルダ内には次のようなファイルがそれぞれ存在します。
(Bフォルダにはb1.txt, b2.txt, b3.txt、Cフォルダにはc1.txt, c2.txt, c3.txt)
最終的には、~\Qiita\Copy-Item\フォルダ\バックアップ
を作成、そこに上記のフォルダ構成をまるごとコピーし…
~\Qiita\Copy-Item\フォルダ\バックアップ
の構成が、最初の~\Qiita\Copy-Item\フォルダ
と同じになるようにします。
問題発生
一番最初にスクリプトを実行しました。(カレントディレクトリは~\Qiita\Copy-Item\フォルダ
とします。)
Get-ChildItem -Path . | #カレントディレクトリのアイテムを取得
ForEach-Object {
Copy-Item -Recurse $_.FullName ".\バックアップ" #バックアップにアイテムをコピー
}
しかし実行した結果、バックアップフォルダは次のようになりました。
B, Cは想定したとおりにコピーされていますが、
Aはフォルダまるごとではなく、フォルダ内のファイルのみコピーされてしまいました。
なぜ?
Copy-Itemはコピー先パスのフォルダが「存在するとき」と「存在しないとき」で動きが異なるからです。
フォルダが存在するとき
コピー元フォルダがコピー先フォルダ内にそのままコピーされます。(本来やりたかった動き!)
フォルダが存在しないとき
コピー元フォルダの名称が、コピー先フォルダの名称に変更されたフォルダが作成されます。( 問題発生での動き…)
具体的に
問題発生で実行したスクリプトでは、次のような動きをしていました。
1.でフォルダ"バックアップ"が存在しないために、
フォルダAの名称が「バックアップ」になっただけのフォルダがコピーされていたのでした。
解決!
New-Item -Path "~\Qiita\Copy-Item\フォルダ\バックアップ"; #事前にバックフォルダを作成する
Get-ChildItem -Path . |
Where-Object FullName -NotLike "*\バックアップ" | #バックアップフォルダは除く
ForEach-Object {
Copy-Item -Recurse $_.FullName ".\バックアップ"
}
事前にバックアップフォルダを作成しておくことで、想定した動きになりました!
ちなみにWhere-Objectでは、事前に作成したバックアップフォルダを除外し、
バックアップフォルダ内にバックアップフォルダがコピーされないようにしています。
おわりに
こうして記事にして改めて問題を振り返ると、なかなかに初歩的なミスをしてるな~と感じました。
もっとスマートなやり方があれば、ご教授いただけるとありがたいです。
それではまた、次の記事で。