0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Copy-Item】コピー先フォルダの存在に気をつけろ!【PowerShell】

Last updated at Posted at 2022-08-25

はじめに

どうも、ATLのヴィリアスです。

最近、社内でとあるフォルダの整理をしました。
そのときに「とりあえず整理前フォルダのバックアップを取っておこう」ということで、
何も考えずにPowerShellでCopy-Itemをしたら「????」な問題が発生してしまいました。

問題を解決するまで少し悩んでしまったので、今後忘れないように記事にすることにします。

※免責事項(必ず、ご一読ください)
  記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
  また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
  必ずしも正確性を保証するものではありません。ご了承ください。

やろうとしたこと

とあるフォルダの構成を、そのフォルダ内にバックアップフォルダを作成し、そこにPowerShellでまるごとコピーする。

具体的に

サンプルとして、~\Qiita\Copy-Item\フォルダにA, B, Cの3フォルダが存在するとします。
今回の記事では、このフォルダ構成のバックアップを取っていきます。
image.png

ちなみに、A, B, Cのフォルダ内には次のようなファイルがそれぞれ存在します。
(Bフォルダにはb1.txt, b2.txt, b3.txt、Cフォルダにはc1.txt, c2.txt, c3.txt)
image.png

最終的には、~\Qiita\Copy-Item\フォルダ\バックアップを作成、そこに上記のフォルダ構成をまるごとコピーし…
image.png

~\Qiita\Copy-Item\フォルダ\バックアップの構成が、最初の~\Qiita\Copy-Item\フォルダと同じになるようにします。
image.png

問題発生

一番最初にスクリプトを実行しました。(カレントディレクトリは~\Qiita\Copy-Item\フォルダとします。)

PowerShell
Get-ChildItem -Path . | #カレントディレクトリのアイテムを取得
ForEach-Object {
    Copy-Item -Recurse $_.FullName ".\バックアップ" #バックアップにアイテムをコピー
}

しかし実行した結果、バックアップフォルダは次のようになりました。
image.png

B, Cは想定したとおりにコピーされていますが、
Aはフォルダまるごとではなく、フォルダ内のファイルのみコピーされてしまいました。

なぜ?

Copy-Itemはコピー先パスのフォルダが「存在するとき」と「存在しないとき」で動きが異なるからです。

フォルダが存在するとき

コピー元フォルダがコピー先フォルダ内にそのままコピーされます。(本来やりたかった動き!)

フォルダが存在しないとき

コピー元フォルダの名称が、コピー先フォルダの名称に変更されたフォルダが作成されます。( 問題発生での動き…)

具体的に

問題発生で実行したスクリプトでは、次のような動きをしていました。

  1. ForEach-Objectでの1回目のCopy-Itemで、フォルダAの名称が「バックアップ」になっただけのものを作成 (中身はフォルダAと同じ)
    image.png

  2. 2回目、3回目のCopy-Itemで、フォルダ"バックアップ"内にフォルダB, フォルダCをコピー
    image.png

1.でフォルダ"バックアップ"が存在しないために、
フォルダAの名称が「バックアップ」になっただけのフォルダがコピーされていたのでした。

解決!

PowerShell
New-Item -Path "~\Qiita\Copy-Item\フォルダ\バックアップ"; #事前にバックフォルダを作成する

Get-ChildItem -Path . |
Where-Object FullName -NotLike "*\バックアップ" | #バックアップフォルダは除く
ForEach-Object {
    Copy-Item -Recurse $_.FullName ".\バックアップ"
}

image.png

事前にバックアップフォルダを作成しておくことで、想定した動きになりました!

ちなみにWhere-Objectでは、事前に作成したバックアップフォルダを除外し、
バックアップフォルダ内にバックアップフォルダがコピーされないようにしています。

おわりに

こうして記事にして改めて問題を振り返ると、なかなかに初歩的なミスをしてるな~と感じました。
もっとスマートなやり方があれば、ご教授いただけるとありがたいです。

それではまた、次の記事で。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?