9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

Windows標準機能で最速のファイル検索コマンドをきめろ!!

Last updated at Posted at 2023-07-03

はじめに

みなさん、毎日windowsでファイルしてますか!?
私はしています。どこかの試算だとファイル検索に使用している時間は、1年で1か月に相当するとか聞いたことがあります。
そこで、私がWindows最速のファイル検索コマンドを探しました。

前提

  • Windows
  • 閲覧権限があるフォルダ
  • Powershell

Windows 最速コマンド

以下の5つのコマンドで計測しました。
また、計測にはMeasure-Commandを使用しています。
-Expressionで計測したいコマンドを指定することで計測できます。
使用例: Measure-Command -Expression { Get-Process }

コマンド 説明 使用例
Get-ChildItem PowerShellの標準コマンド Get-ChildItemを使い、指定したパターンに一致するファイルを再帰的に探索します。 Get-ChildItem -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue
[System.IO.Directory]::EnumerateFiles .NETのメソッドである [System.IO.Directory]::EnumerateFiles を使い、指定したパターンに一致するファイルを再帰的に探索します。 [System.IO.Directory]::EnumerateFiles($rootPath, $pattern, 'AllDirectories')
ls PowerShellの別名(エイリアス)である ls(本来は Get-ChildItemのエイリアス)を使い、指定したパターンに一致するファイルを再帰的に探索します。 ls -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue
DirectoryInfo .NETの System.IO.DirectoryInfoクラスを使い、指定したパターンに一致するファイルを再帰的に探索します。 $di = New-Object System.IO.DirectoryInfo($rootPath); $di.GetFiles($pattern, 'AllDirectories')
robocopy robocopyコマンドを使い、指定したパターンに一致するファイルを再帰的に探索します。 robocopy $rootPath NULL $pattern /L /S /NJH /NJS /NDL /NS

これらのコマンドは、すべてファイルを探索するためのものですが、各コマンドにはその特性や速度、そして使用状況や環境による限定的な問題(OneDriveとの相性など)が存在します。

スクリプト紹介

1. Get-ChildItemによる検索と計測

基本の検索はGet-ChildItemじゃないでしょうか。
PowerShellの標準コマンドで、指定されたパスのアイテム(ディレクトリやファイル)を取得します。
-Pathで指定されたパス($rootPath)から、-Filterで指定されたパターン($pattern)に一致するアイテムを再帰的に(-Recurse)探索しています。-ErrorAction SilentlyContinueはエラーが発生しても処理を続行するためのオプションです。

$getChildItemTime = Measure-Command -Expression {
    Get-ChildItem -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
        $_.FullName
    }
}
Write-Output "Get-ChildItem time: $($getChildItemTime.TotalMilliseconds) ms"

2. [System.IO.Directory]::EnumerateFilesによる検索と計測

.NET Frameworkのメソッドで、指定されたパスからパターンに一致するファイルを再帰的に検索します。ここでは$rootPathから$patternに一致するファイルを再帰的に('AllDirectories')探索しています。

$enumerateFilesTime = Measure-Command -Expression {
    [System.IO.Directory]::EnumerateFiles($rootPath, $pattern, 'AllDirectories')
}
Write-Output "[System.IO.Directory]::EnumerateFiles time: $($enumerateFilesTime.TotalMilliseconds) ms"

3. lsによる検索と計測

みなさんおなじみのlsですね、実は検索もできます。
lsはUnix系システムで使われるコマンドで、PowerShellではGet-ChildItemのエイリアス(別名)として機能します。このコマンドも$rootPathから$patternに一致するアイテムを再帰的に探索します。

$lsTime = Measure-Command -Expression {
    ls -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
        $_.FullName
    }
}
Write-Output "ls time: $($lsTime.TotalMilliseconds) ms"

4. DirectoryInfoによる検索と計測

System.IO.DirectoryInfoは.NET Frameworkのクラスで、ファイルシステムのディレクトリを表します。GetFilesメソッドは指定されたパターンに一致するファイルを再帰的に取得します。ここでは$rootPathから$patternに一致するファイルを再帰的に取得しています。

$directoryInfoTime = Measure-Command -Expression {
    $di = New-Object System.IO.DirectoryInfo($rootPath)
    $di.GetFiles($pattern, 'AllDirectories')
}
Write-Output "DirectoryInfo time: $($directoryInfoTime.TotalMilliseconds) ms"

5. robocopyによる検索と計測

robocopyはRobust File Copyの略で、Windowsで使用される強力なファイルコピーのコマンドです。ただし、ここではファイルのコピーではなく、/Lオプションによってリストのみを生成してファイルを探索しています。/Sオプションはサブディレクトリも探索することを意味し、/NJH, /NJS, /NDL, /NSはヘッダ、サマリ、ディレクトリ名、ファイルサイズの出力を抑制するためのオプションです。

$robocopyTime = Measure-Command -Expression {
    robocopy $rootPath NULL $pattern /L /S /NJH /NJS /NDL /NS | Out-Null
}
Write-Output "robocopy time: $($robocopyTime.TotalMilliseconds) ms"

最速はだれ!?

では計測していきます!

Explorerのフォルダ検索時間(ローカルフォルダ)

コマンド 実行時間 (s)
robocopy 0.233
[System.IO.Directory]::EnumerateFiles 0.244
DirectoryInfo 0.280
Get-ChildItem 0.417
ls 0.533

OneDriveの検索時間

Onedriveとの相性は相当あるっぽいですね。

コマンド 実行時間 (s)
robocopy 0.047
[System.IO.Directory]::EnumerateFiles 8.895
DirectoryInfo 7.688
Get-ChildItem 57.780
ls 70.540

ランキング

ランキング OneDriveの検索 Explorerの検索
1 (最速) robocopy robocopy
2 [System.IO.Directory]::EnumerateFiles [System.IO.Directory]::EnumerateFiles
3 DirectoryInfo DirectoryInfo
4 Get-ChildItem Get-ChildItem
5 (最遅) ls ls

これらの結果から、robocopyが最適であることがわかりました!
使ったことなかったし、存在を知らなかった。。

みなさん、あしたからrobocopyを使ってファイル検索しましょう(なくさないようなフォルダ管理をするのが一番良い)

ソース全体

$rootPath = "C:\Users\sakaj\OneDrive - WellBee\" # 探索したいディレクトリのパス
$pattern = "hoge.txt" # 検索したいパターンを指定

# Get-ChildItemによる検索と計測
$getChildItemTime = Measure-Command -Expression {
    Get-ChildItem -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
        $_.FullName
    }
}
Write-Output "Get-ChildItem time: $($getChildItemTime.TotalMilliseconds) ms"

# [System.IO.Directory]::EnumerateFilesによる検索と計測
$enumerateFilesTime = Measure-Command -Expression {
    [System.IO.Directory]::EnumerateFiles($rootPath, $pattern, 'AllDirectories')
}
Write-Output "[System.IO.Directory]::EnumerateFiles time: $($enumerateFilesTime.TotalMilliseconds) ms"

# lsによる検索と計測
$lsTime = Measure-Command -Expression {
    ls -Path $rootPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
        $_.FullName
    }
}
Write-Output "ls time: $($lsTime.TotalMilliseconds) ms"

# DirectoryInfoによる検索と計測
$directoryInfoTime = Measure-Command -Expression {
    $di = New-Object System.IO.DirectoryInfo($rootPath)
    $di.GetFiles($pattern, 'AllDirectories')
}
Write-Output "DirectoryInfo time: $($directoryInfoTime.TotalMilliseconds) ms"

# robocopyによる検索と計測
$robocopyTime = Measure-Command -Expression {
    robocopy $rootPath NULL $pattern /L /S /NJH /NJS /NDL /NS | Out-Null
}
Write-Output "robocopy time: $($robocopyTime.TotalMilliseconds) ms"

9
5
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
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?