LoginSignup
3
4

More than 1 year has passed since last update.

PowerShellでフォルダとファイル名を正規表現で絞り込んで一覧を取得する

Last updated at Posted at 2021-12-25

やりたいこと

  1. ファイル名一覧を取得したい。
  2. 正規表現で取得対象のフォルダ・ファイル名を絞り込みたい。(bkフォルダやoldフォルダを対象外にするなど)

結論

ソースコード

find.ps1
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でコマンドライン引数を指定できる。

sample.ps1
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

指定フォルダ配下の全ファイル一覧を正規表現で絞り込んで取得する

上記のことを踏まえて、表題の機能を実現すると以下のようになる。

find.ps1
# 引数
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 }
3
4
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
3
4