【PowerShell】複数のフォルダに格納されているファイルの有無を一括で確認する方法
この記事では、以下のような状況において、PowerShellを使用してファイルの有無を確認する方法を紹介します。
想定している状況
- 人ごとにフォルダが作成されている。
- それぞれのフォルダの中に、提出書類が格納されている。
イメージとしては、以下のような状況です。
上記の例では、それぞれの人のフォルダごとに、①パスポート、②運転免許証、③健康保険証という3種類のファイルが格納されることを想定しています。
このような場合、誰のフォルダにはファイルが入っていて、誰のフォルダにはまだ入っていないのかを確認するのが、若干面倒な作業になります。
サンプルのように4人分しかフォルダがないのであれば、フォルダをひとつずつ開いていくこともできるでしょう。
しかし、この方法だと、100人分のフォルダがあった場合に、膨大な時間がかかることになります。
そこで、この記事では、フォルダの中に入っているファイルの有無を一度に確認できる方法を紹介します。
Windowsに標準で搭載されているPowerShellという機能を使用するため、この方法を使用するために新たなツールをインストールする必要する必要はありません。
確認手順
それぞれのフォルダにファイルが入っているかどうかを確認する手順は、大きく2段階になります。
- PowerShellを起動する。
- ファイル有無を確認するコマンドを実行する。
1. PowerShellを起動する
まず、PowerShellの起動方法を紹介します。
PowerShellを起動するには、起動したいフォルダを開いた状態で、Shiftキーを押しながらフォルダ内を右クリックし、「Power Shell ウィンドウをここで開く(s)」をクリックします。
右クリックする際にShiftキーを押している必要があることに注意してください。Shiftキーを押していない状態で右クリックしても「Power Shell ウィンドウをここで開く(s)」メニューは表示されません。
2. ファイル有無を確認するコマンドを実行する
PowerShellを開くことができたら、以下のコマンドを実行します。
コマンド
Get-ChildItem -Attributes Directory | ForEach-Object { if ( Test-Path -Path “$_/パスポート.txt" ) { “$_ : OK” } else { ”$_ : NG” } }
コマンドの中にある「パスポート.txt」の部分は、探したいファイル名に置き換えてください。
コマンドを実行すると、以下のような結果が得られます。
実行結果
山田 太郎 : NG
木村 美智子 : OK
田中 佐知子 : OK
鈴木 光太郎 : OK
「パスポート.txt」が格納されているかどうかを「OK」「NG」という形で一度に確認できるようになりました。
コード解説
ここからは、PowerShellコマンドの理解を深めたい方向けに、上記のコマンドの詳細について解説いたします。
Get-ChildItemコマンド
Get-ChildItemコマンドは、現在のフォルダの中にあるファイルやフォルダの一覧を出力するコマンドです。
上記の例では、PowerShellを「C:\work\powershell」フォルダで開いているので、「Get-ChildItem」コマンドだけを実行すると、以下のように「C:\work\powershell」フォルダの内容が出力されます。
Windowsのコマンドプロンプトを使用している方は、「dir」コマンドと同じ、と考えていただくとわかりやすいかもしれません。
Get-ChildItemには、いくつかオプションがあります。
特定の条件を満たす-Pathオプションや、サブフォルダの内容も出力する-Recurseオプションなどです。
全てのオプションの内容を確認したい場合は、MicrosoftのHPを参照してください。
Get-ChildItem (Microsoft.PowerShell.Management) - PowerShell | Microsoft Learn
Get-ChildItem コマンドレットは、指定された 1 つ以上の場所にある項目を取得します。 項目がコンテナーの場合は、コンテナーの中にある項目 (子項目) を取得します。 Re…
-Attribute オプション
上で紹介したコマンドでは、Get-ChildItemの-Attributeオプションを使用しています。
このオプションでは、ファイルだけを検索したり、フォルダだけを検索したり、あるいは、隠しファイルだけを検索したりといったように、特定の属性を持つものだけを検索対象に指定することができます。
紹介したコマンドでは、「-Attribute Directory」と指定することによって、フォルダだけを検索対象としています。
パイプ
次に、「|」についてです。
これは、“パイプ“と呼ばれている処理で、「左側で実行した結果に対して、右側に記載された処理を実行する」という意味になります。
上記の例で言うと、Get-ChildItemを実行することで各個人ごとのフォルダが取得され、取得されたフォルダに対して、右側に記載したコマンド(ForEach-Objectで始まるコマンド)を実行することになります。
ForEach-Objectと自動変数
ForEach-Objectコマンドは、パイプで渡ってきた情報のひとつひとつに対して{}に記載したコマンドを実行していく、という意味になります。
この「パイプで渡ってきた情報のひとつひとつに対して」という部分がポイントです。
上記のコマンドでは、パイプの左側にあるGet-ChildItemコマンドで4つのフォルダの情報が取得され、その情報がパイプを経由してForEach-Objectコマンドに渡ってくることになります。
ForEach-Objectコマンドは、渡ってきた4つのフォルダの情報ひとつひとつに対して{}内のコマンドを実行していくのです。
つまり、「山田 太郎」フォルダに対して{}の処理を実行し、「田中 佐知子」フォルダに対して{}内の処理を実行し、・・・ということを4フォルダ分繰り返すことになります。
if文とTest-Pathコマンド
では、{}内にある以下のコマンドは何を実行しているのでしょうか。
コード
if ( Test-Path -Path “$_/パスポート.txt" ) { “$_ : OK” } else { ”$_ : NG” }
このコマンドは、大まかに見ると、以下のような構造になっています。
構造
if ( ※1 ) { ※2 } else { ※3 }
これは、※1の条件を満たしている場合は※2のコマンドを実行し、そうでない(※1の条件を満たさない)場合は※3のコマンドを実行する、という意味になります。
プログラミングをやっている方であれば、条件分岐の処理であると考えればイメージしやすいかもしれません。
次に※1の部分を見ていきましょう。※1は「Test-Path -Path "$/パスポート.txt"」となっています。
Test-Pathコマンドは、-Pathオプションに指定されたファイルが存在するかどうかを判定するコマンドになります。つまり、”$_/パスポート.txt”が存在するかどうかを判定している処理になります。
では、「$_」というのは何を指しているのでしょうか。
ここで、「ForEach-Objectと自動変数」のところで、「パイプで渡ってきた情報のひとつひとつに対して」処理をすることがポイントだったことを思い出してください。
「$」というのは、この“ひとつひとつの情報”を指しています。
つまり、「山田 太郎」フォルダの処理をしているときは、「$_」は「山田 太郎」フォルダを指し、「田中 佐知子」フォルダの処理をしているときは、「$_」は「田中 佐知子」フォルダを指すことになります。
これによって、例えば「山田 太郎」フォルダを処理しているときは、「Test-Path -Path “$_/パスポート.txt”」は「Test-Path -Path "山田 太郎/パスポート.txt"」を実行しているのと同じ意味になり、「山田 太郎」フォルダにパスポート.txtファイルがあるかどうかをチェックすることができているのです。
※2にある「”$_ : OK"」と※3にある「$_ : NG」は、いずれも出力する文字列を指定しています。
「$_」というのが“ひとつひとつの情報”を指しているため、「”$_ : OK"」とすることで、「$_」の部分にフォルダの名称が当てはめられ、「田中 佐知子 : OK」といった結果が出力されることになります。
おわりに
PowerShellを使用して、複数のフォルダにある同名ファイルの有無を一度に確認する方法を紹介しました。
PowerShellのコマンドを使用することで、ひとつひとつやっていくと時間のかかる作業でも、一度にまとめてできることが少なくありません。
この記事で紹介した方法を活用すると同時に、PowerShellの理解を深めるきっかけにしてもらえればと思います。