LoginSignup
4
0

More than 1 year has passed since last update.

PowerShellで指定フォルダ以下にあるファイルの一覧(長いパス対応)を得る

Last updated at Posted at 2019-09-26

概要

ファイルサーバ内のファイルをうち、特定の物を処理するスクリプトをPowerShellで作ろうと、Get-ChildItem *** -Recurseしたところ、階層が深くパスが260文字以上となるファイルがたくさんあることがわかった。

解決法は何通りかあるものの、robocopyを使うのが簡単そうだったので、長いファイル名のフルパスを得る関数を作ってみた。
ついでに、長いパス名のファイルが無い場合でもGet-ChildItemよりも2倍程度高速。

つくったもの

function Get-ChildFilePath {
  [CmdletBinding()]
  [OutputType([String[]])]
  param (
    [Parameter(Mandatory,ValueFromPipeline)]
    [string]$Path
  )

  BEGIN {
    $notexist = 'C:\DOESNOTEXIST';
    while (Test-Path $notexist){
      $notexist += Get-Random $(48..57+97..122) | % {[char]$_}
    }
  }

  PROCESS {
    if( Test-Path $Path ){
      $list = robocopy.exe $Path $notexist /L /E /B /NP /FP /NS /NC /NJH /NJS /NDL |
        ForEach-Object { $_.Trim() } | Where-Object { $_.Length -gt 0 }
      @($list)
    } else {
      @()
    }
  }
}

※ PowerShellは管理者権限が必要

説明

robocopyで使っているオプションの説明は下記(robocopy /?から抜粋)。

/L :: リストのみ - いずれのファイルにも、コピー、タイムスタンプの追加、または削除を実施しません。
/E :: 空のディレクトリを含むサブディレクトリをコピーします。
/B :: バックアップ モードでファイルをコピーします。
/NP :: 進行状況なし - コピーの完了率を表示しません。
/FP :: 出力にファイルの完全なパス名を含めます。
/NS :: サイズなし - ファイル サイズをログに記録しません。
/NC :: クラスなし - ファイル クラスをログに記録しません。
/NDL :: ディレクトリなし - ディレクトリ名をログに記録しません。
/NJH :: ジョブ ヘッダーがありません。
/NJS :: ジョブ要約がありません。

以上のオプションとコピー先として存在しないフォルダを指定してrobocopy.exeを呼び出すと、コピー元に指定したフォルダ以下にあるファイルの、フルパスのリストが出力されるので、無駄な空白を除いたものを出力する。

また結果が0行だったり1行だったりしたときに返り値の型が変わらないよう、@()で囲んで必ず配列が返るようにした。

使い方

単純に指定したフォルダ以下の文字列のリストを得る。

Get-ChildFilePath "C:\Users\hogehoge\Documents"

Get-ChildItemと同様にSystem.IO.FileSystemInfoを得るには、Get-Itemに渡せばOK。

Get-ChildFilePath "C:\Users\hogehoge\Documents" | Get-Item

ファイル名でフィルタをかける場合は、先に文字列を条件に絞ってからGet-Itemをしたほうが高速(なので敢えてGet-ChildItemとは互換のないようにした)。

Get-ChildFilePath "C:\Users\hogehoge\Documents" | ? { $_ -like "*.png" } | Get-Item
4
0
1

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
4
0