くまくまの業務日誌

Markdown記法で徒然に書いてみましょう。

DIR → Get-ChildItem

ファイルとディレクトリに関する基本事項のピックアップ&スニペット

エラーの扱い方について

他のプロセスが出力中で、読み込むことができないファイルをスキップする場合は、
" -ErrorAction SilentlyContinue"を付加します。
あるいは、$ErrorActionPreference = "SilentlyContinue"を実行しておきます。
とは言っても、エラー情報を捨てる訳にも行きませんので、エラー情報を変数に格納しておき、後で出力します。

-ErrorVariable errorInfo  # エラー情報を上書きしていく場合 (ここで$を付けない)
-ErrorVariable +errorInfo # エラー情報を追記していく場合 (ここで$を付けない)
Write-Host $errorInfo[0]

ディレクトリ一覧を取得する。

$targetDirectory = "C:\windows\Temp"
Get-ChildItem $targetDirectory
    ディレクトリ: C:\windows\Temp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/06/19     22:32                FA345C83-F785-4C40-AB34-2323134FE882-Sigs
d-----       2020/06/19     22:38                MsEdgeCrashpad
-a----       2020/06/19     22:38             53 af397ef28e484961ba48646a5d38cf54.db.ses
-a----       2020/06/07      1:54          12621 CompatibilityList.xml
-a----       2020/06/16     23:01           4554 dd_setup_20200616230105.log
-a----       2020/06/16     23:01              0 dd_setup_20200616230105_errors.log
-a----       2020/06/16     23:07        1398494 dd_setup_20200616230115.log
-a----       2020/06/16     23:01           5392 dd_setup_20200616230115_000_Microsoft.VisualStudio.Product.Community.log
-a----       2020/06/16     23:01         258926 dd_setup_20200616230115_001_Microsoft.VisualStudio.LiveShare.log
-a----       2020/06/16     23:02         726558 dd_setup_20200616230115_002_Microsoft.VisualStudio.LiveShare.log
-a----       2020/06/16     23:06            165 dd_setup_20200616230115_003_Unity3d.x64.log

ディレクトリを再帰しながら、全ての一覧を取得する。 [-Recurse]

+ファイル名にワイルドカードを使用して対象選択+文字列の連結。

$targetDirectory = "C:\windows\Temp"
$targetFileName = "*.log"
Get-ChildItem -Recurse $targetDirectory\$targetFileName
    ディレクトリ: C:\windows\Temp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/06/16     23:01           4554 dd_setup_20200616230105.log
-a----       2020/06/16     23:01              0 dd_setup_20200616230105_errors.log
-a----       2020/06/16     23:07        1398494 dd_setup_20200616230115.log
-a----       2020/06/16     23:01           5392 dd_setup_20200616230115_000_Microsoft.VisualStudio.Product.Community.log
-a----       2020/06/16     23:01         258926 dd_setup_20200616230115_001_Microsoft.VisualStudio.LiveShare.log
-a----       2020/06/16     23:02         726558 dd_setup_20200616230115_002_Microsoft.VisualStudio.LiveShare.log
-a----       2020/06/16     23:06            165 dd_setup_20200616230115_003_Unity3d.x64.log
-a----       2020/06/16     23:07          11227 dd_setup_20200616230115_004_Microsoft.VisualStudio.Product.Community.log
-a----       2020/06/16     23:01              0 dd_setup_20200616230115_errors.log

ディレクトリのみをリストアップする。 [-Directory]

$targetDirectory = "C:\windows\Temp"
Get-ChildItem -Directory $targetDirectory
    ディレクトリ: C:\windows\Temp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/06/19     22:32                FA345C83-F785-4C40-AB34-2323134FE882-Sigs
d-----       2020/06/19     22:38                MsEdgeCrashpad

ファイルのみをリストアップする。 [-File]

$targetDirectory = "C:\windows\Temp"
Get-ChildItem -File $targetDirectory
    ディレクトリ: C:\windows\Temp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/06/19     22:38             53 af397ef28e484961ba48646a5d38cf54.db.ses
-a----       2020/06/07      1:54          12621 CompatibilityList.xml
-a----       2020/06/16     23:01           4554 dd_setup_20200616230105.log
-a----       2020/06/16     23:01              0 dd_setup_20200616230105_errors.log
-a----       2020/06/16     23:07        1398494 dd_setup_20200616230115.log
-a----       2020/06/16     23:01           5392 dd_setup_20200616230115_000_Microsoft.VisualStudio.Product.Community.log

ファイル名を相対パスのみで一覧取得する。[-Name]

$targetDirectory = "C:\windows\Temp"
Get-ChildItem -Recurse -File -Name $targetDirectory
af397ef28e484961ba48646a5d38cf54.db.ses
CompatibilityList.xml
dd_setup_20200616230105.log
dd_setup_20200616230105_errors.log
dd_setup_20200616230115_000_Microsoft.VisualStudio.Product.Community.log
dd_setup_20200616230115_002_Microsoft.VisualStudio.LiveShare.log
VSIXodgqpfok.vsix
MsEdgeCrashpad\metadata
MsEdgeCrashpad\settings.dat

ファイル名を絶対パスのみで一覧取得する。

$targetDirectory = "C:\windows\Temp"
Get-ChildItem -Recurse $targetDirectory | Select-Object -property FullName
FullName
--------
C:\windows\Temp\FA345C83-F785-4C40-AB34-2323134FE882-Sigs
C:\windows\Temp\MsEdgeCrashpad
C:\windows\Temp\af397ef28e484961ba48646a5d38cf54.db.ses
C:\windows\Temp\CompatibilityList.xml
C:\windows\Temp\dd_setup_20200616230105_errors.log
C:\windows\Temp\dd_setup_20200616230115.log
C:\windows\Temp\dd_setup_20200616230115_001_Microsoft.VisualStudio.LiveShare.log
C:\windows\Temp\dd_setup_20200616230115_003_Unity3d.x64.log
C:\windows\Temp\dd_setup_20200616230115_errors.log
C:\windows\Temp\dd_VSIXInstaller_20200616225936_0ff4.log
C:\windows\Temp\mat-debug-7936.log
C:\windows\Temp\MsEdgeCrashpad\settings.dat

Excludeを使用して不要なディレクトリを外して一覧取得する。[-Exclude]

$targetDirectory = "C:\Windows\system32"
Get-ChildItem -Recurse -Exclude @("*.exe", "*.dll", "*.cpl") -Name $targetDirectory
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV3B-PropertyBag.bag
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV3C-manifest.ini
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV3C-PropertyBag.bag
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV3D-manifest.ini
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV3I-manifest.ini
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV5B-manifest.ini
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saMV5B-PropertyBag.bag
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\saSP-pipelineconfig.xml
DriverStore\FileRepository\prnsacl1.inf_amd64_01567720b35ae842\smpclrc2.gpd
DriverStore\FileRepository\prntscl2.inf_amd64_64886520e82c3cce\prntscl2.cat
DriverStore\FileRepository\prntscl2.inf_amd64_64886520e82c3cce\prntscl2.inf

そもそも、Get-ChildItem はなにを返すのか?

出力内容から"Get-Member"を使って、propertyだけを抽出します。

$targetDirectory = ".."
Get-ChildItem $targetDirectory | Get-Member | Where-Object { $_.MemberType -eq "Property"}
   TypeName: System.IO.DirectoryInfo

Name              MemberType Definition
----              ---------- ----------
Attributes        Property   System.IO.FileAttributes Attributes {get;set;}
CreationTime      Property   datetime CreationTime {get;set;}
CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}
Exists            Property   bool Exists {get;}
Extension         Property   string Extension {get;}
FullName          Property   string FullName {get;}
LastAccessTime    Property   datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}
LastWriteTime     Property   datetime LastWriteTime {get;set;}
LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}
Name              Property   string Name {get;}
Parent            Property   System.IO.DirectoryInfo Parent {get;}
Root              Property   System.IO.DirectoryInfo Root {get;}

これだけの情報を返してくれます。これらを駆使して、スクリプトを書いていきます。
また、Get-Menberは「こいつ、なにを返すんだ?」というときによく使います。

再帰しながら、ファイル情報を取得します。

自力で再帰するので、カレントディレクトリから 深い階層に移動するタイミングで状況判断ができます。つまり、制御はディレクトリ移動の際にこちらに戻される訳です。そのタイミングで、サマリを取ったり、プログレスを出したりできます。

function recursiveFileSearch($targetFolderName, $targetExtension) {
    Write-Host $targetFolderName -ForegroundColor Green
    $collection = Get-ChildItem $targetFolderName -ErrorAction SilentlyContinue -ErrorVariable errorInfo
    if ($errorInfo.Length -gt 0) {
        Write-Warning $errorInfo[0]
        Start-Sleep -Seconds 1
    }
    foreach ($item in $collection) {
        if ($item.Extension.trim() -eq $targetExtension) {
            $output = "{0}`t{1}`t{2}" -F $item.FullName, $item.Extension, $item.LastWriteTime
            Write-Output $output
            Start-Sleep -Milliseconds 200
        }
        if ($item.Attributes -eq "Directory") {
            # ディレクトリを再帰調査します。
            recursiveFileSearch $item.FullName $targetExtension
        }
    }
}
recursiveFileSearch "C:\Windows" ".ps1" > ExecuteFileList.log

コンソール出力

C:\Windows\Containers
C:\Windows\Containers\serviced
C:\Windows\CSC
WARNING: パス 'C:\Windows\CSC' へのアクセスが拒否されました。
C:\Windows\Cursors
C:\Windows\debug
C:\Windows\diagnostics

ファイル出力

C:\Windows\diagnostics\scheduled\Maintenance\CL_Utility.ps1  .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\RS_AdminDiagnosticHistory.ps1  .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\RS_MachineWERQueue.ps1 .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\RS_SyncSystemTime.ps1  .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\RS_UserDiagnosticHistory.ps1   .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\RS_UserWERQueue.ps1    .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\TS_DiagnosticHistory.ps1   .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\TS_InaccurateSystemTime.ps1    .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\scheduled\Maintenance\TS_WERQueue.ps1    .ps1    2018/04/12 8:34:38
C:\Windows\diagnostics\system\AERO\CL_AeroFeature.ps1   .ps1    2018/04/12 8:34:37