やりたいこと
- ファイル名一覧を取得したい。
- 正規表現で取得対象のフォルダ・ファイル名を絞り込みたい。(bkフォルダやoldフォルダを対象外にするなど)
結論
ソースコード
param (
[string]$fileNameMatch,
[string]$path,
[string]$fileNameNotMatch,
[string]$dirMatch,
[string]$dirNotMatch,
[switch]$recurse
)
$fileList = Get-ChildItem -File -Path $path -Recurse:$recurse
if (0 -ne $fileNameMatch.Length) { $fileList = $fileList | Where-Object { $_.Name -match $fileNameMatch } }
if (0 -ne $fileNameNotMatch.Length) { $fileList = $fileList | Where-Object { $_.Name -notmatch $fileNameNotMatch } }
if (0 -ne $dirMatch.Length) { $fileList = $fileList | Where-Object { $_.DirectoryName -match $dirMatch } }
if (0 -ne $dirNotMatch.Length) { $fileList = $fileList | Where-Object { $_.DirectoryName -notmatch $dirNotMatch } }
$fileList | ForEach-Object { $_.FullName }
実行例
フォルダ構成
C:.
│ find.ps1
│ サンプル01.txt
│ サンプル02.txt
│ サンプル03.txt
│
├─bk
│ サンプル01.txt
│ サンプル02.txt
│
└─old
20211225_サンプル01.txt
20211225_サンプル02.txt
ファイル名一覧を取得する
> ./find.ps1
C:\Users\*****\Documents\サンプル\find.ps1
C:\Users\*****\Documents\サンプル\サンプル01.txt
C:\Users\*****\Documents\サンプル\サンプル02.txt
C:\Users\*****\Documents\サンプル\サンプル03.txt
recurse
オプションを指定するとサブフォルダも取得できる。
> ./find.ps1 -recurse
C:\Users\*****\Documents\サンプル\find.ps1
C:\Users\*****\Documents\サンプル\サンプル01.txt
C:\Users\*****\Documents\サンプル\サンプル02.txt
C:\Users\*****\Documents\サンプル\サンプル03.txt
C:\Users\*****\Documents\サンプル\bk\サンプル01.txt
C:\Users\*****\Documents\サンプル\bk\サンプル02.txt
C:\Users\*****\Documents\サンプル\old\20211225_サンプル01.txt
C:\Users\*****\Documents\サンプル\old\20211225_サンプル02.txt
ファイル名で絞り込む
> ./find.ps1 -recurse -fileNameMatch "01"
C:\Users\*****\Documents\サンプル\サンプル01.txt
C:\Users\*****\Documents\サンプル\bk\サンプル01.txt
C:\Users\*****\Documents\サンプル\old\20211225_サンプル01.txt
正規表現パターンに含まれない条件も同時に指定する場合、下記のように実行する。
> ./find.ps1 -recurse -fileNameMatch "01" -fileNameNotMatch "_"
C:\Users\*****\Documents\サンプル\サンプル01.txt
C:\Users\*****\Documents\サンプル\bk\サンプル01.txt
フォルダで絞り込む
> ./find.ps1 -recurse -dirMatch "bk"
C:\Users\*****\Documents\サンプル\bk\サンプル01.txt
C:\Users\*****\Documents\サンプル\bk\サンプル02.txt
bkフォルダとoldフォルダを対象外にする場合、下記のように実行する。
> ./find.ps1 -recurse -dirNotMatch "bk|old"
C:\Users\*****\Documents\サンプル\find.ps1
C:\Users\*****\Documents\サンプル\サンプル01.txt
C:\Users\*****\Documents\サンプル\サンプル02.txt
C:\Users\*****\Documents\サンプル\サンプル03.txt
> ./find.ps1 -recurse -dirNotMatch "bk|old" -fileNameMatch "01"
C:\Users\*****\Documents\サンプル\サンプル01.txt
説明
ファイル名一覧を取得する
Get-ChildItem
コマンドレットでファイル・フォルダの一覧を取得できる。
これにオプションをつけることで、欲しい情報を制限・拡張できる。
Get-ChildItem -File -Path "C:\Users\*****\Documents" -Recurse
Get-ChildItem
コマンドレット
ファイル・フォルダの一覧を取得する。
-File
オプション
ファイルのみを取得する。(フォルダは取得しない)
-Path
オプション
対象のパスを指定する。
Get-ChildItem -Path "対象のパス"
のように使用する。
-Recurse
オプション
サブフォルダも取得する。
取得したファイル名一覧を正規表現で絞り込む
Where-Object
コマンドレットを使用することで、
Get-ChildItem
で取得したオブジェクトにフィルターをかけることができる。
Get-ChildItem -File -Path "C:\Users\*****\Documents" -Recurse | Where-Object { $_.Name -match "regex" }
|
(パイプライン演算子)
前のコマンドレットの結果を次のコマンドレットに送信する。
これによってGet-ChildItem
の取得結果に対してWhere-Object
を適用している。
Where-Object
コマンドレット
指定した条件に一致するオブジェクトのみを返却する。
Where-Object { 条件式 }
のように使用する。
$_
パイプラインで渡されたオブジェクトを表す自動変数。
上記の場合、Get-ChildItem
コマンドレットで取得したオブジェクトを表している。
$_.Name
$_
オブジェクトの中にあるName
プロパティを取得する。
上記の場合、$_
はGet-ChildItem
の取得結果を表しているため、
$_.Name
ではファイル名のみを取得している。
Get-ChildItem
が持っているプロパティはGet-ChildItem | Get-Member -MemberType property
コマンドレットで確認できる。
今回は下記のプロパティを使用する。
- Name: ファイル名
- DirectoryName: フォルダ
- FullName: ファイルのフルパス(フォルダとファイル名を結合したもの)
-match
演算子
正規表現パターンと一致するか否かを返却する。
"対象の文字列" -match "正規表現パターン"
のように使用する。
これと類似で-notmatch
演算子があり、こちらは正規表現パターンと一致しない場合にtrue
を返却する。
コマンドライン引数を設定する
param
でコマンドライン引数を指定できる。
param (
[string]$inputStr,
[switch]$inputBool
)
if (inputBool) {
Write-Host $inputStr
}
Write-Host $inputStr
[]
で引数の型を指定できる。
string型
コマンドラインに入力された文字列を取得する。
switch型
コマンドラインにオプションとして設定されたか否かを取得する。
実行例
> ./sample.ps1 -inputStr "hello" -inputBool
hello
hello
switch型はオプションとして指定しなかった場合はfalse
になる。
> ./sample.ps1 -inputStr "hello"
hello
switch型は:
を使用して明示的にfalse
を指定することもできる。
> ./sample.ps1 -inputStr "hello" -inputBool:$false
hello
指定フォルダ配下の全ファイル一覧を正規表現で絞り込んで取得する
上記のことを踏まえて、表題の機能を実現すると以下のようになる。
# 引数
param (
# ファイル名に一致させたい正規表現パターン
[string]$fileNameMatch,
# 指定したいフォルダ
[string]$path,
# ファイル名に一致させたくない正規表現パターン
[string]$fileNameNotMatch,
# フォルダに一致させたい正規表現パターン
[string]$dirMatch,
# フォルダに一致させたい正規表現パターン
[string]$dirNotMatch,
# サブフォルダも含むか否か
[switch]$recurse
)
# ファイル名一覧を取得する
$fileList = Get-ChildItem -File -Path $path -Recurse:$recurse
# ファイル名にフィルターをかける
if (0 -ne $fileNameMatch.Length) {
$fileList = $fileList | Where-Object { $_.Name -match $fileNameMatch }
}
if (0 -ne $fileNameNotMatch.Length) {
$fileList = $fileList | Where-Object { $_.Name -notmatch $fileNameNotMatch }
}
# フォルダにフィルターをかける
if (0 -ne $dirMatch.Length) {
$fileList = $fileList | Where-Object { $_.DirectoryName -match $dirMatch }
}
if (0 -ne $dirNotMatch.Length) {
$fileList = $fileList | Where-Object { $_.DirectoryName -notmatch $dirNotMatch }
}
# フルパスを出力する
$fileList | ForEach-Object { $_.FullName }