.png)
私は Windows エコシステム初心者です。数十 (場合によっては数百) のファイルから特定の文字列を検索するプログラムを作成するように指示されました。一致する必要がある文字列は、数字と文字のみで構成される 20 文字未満のシリアル番号です。現在、私のプログラムは次のコマンドを実行しています。
findstr /i /m /s "searchStr" "C:\Directory\To\Search\*.*"
上記のコマンドは動作しますが、速度が遅すぎます。特定のシリアル番号を含む可能性のあるファイルには、最初の行にのみシリアル番号が含まれます。
最初の行にのみ特定の文字列を含むすべてのファイルをディレクトリ内で再帰的に検索する効率的な方法をご存知の方はいませんか?
答え1
PowerShell (v3.0+) では、おそらく...
Get-ChildItem -Path x:\pathto\*.log `
| ForEach-Object {
if (Get-Content -LiteralPath $_ -First 1 `
| Select-String -SimpleMatch -Pattern 'serialnumber')
{
Write-Output $_
}
}
さまざまなパラメーターを使用するとGet-ChildItem
、サブフォルダーなどを再帰的に処理できます。 を使用すると、Get-Content
ファイルからより多くのコンテンツまたはより少ないコンテンツを取得できます。 を使用すると、Select-String
より複雑な一致 (正規表現、大文字と小文字の区別など) を実行できます。
答え2
を使用する必要がない場合は、いくつかのオプションを提案できますfindstr
が、まず、特定のファイルタイプのファイルに検索を制限できるかどうかを確認する必要があります。これにより、確実に処理が高速化されます。
ファイルロケーター ライト私の経験では、ファイルの検索と内容の確認が高速です。開始ディレクトリだけでなく、「ファイル名」(該当する場合) と「含まれるテキスト」フィールドの両方に必ず入力してください。
ag -il "searchStr"
:農業はスピードを重視して作られているため、すぐに結果が表示されます。バイナリファイルはデフォルトでスキップされますが、可能であればファイルタイプで検索を制限してください。以下でも利用可能です。シグウィン。find -exec awk 'BEGIN {IGNORECASE=1} NR==1 && /searchStr/ {print FILENAME": "$0}' {} \;
Cygwin または他の POSIX のような環境が利用できる場合は、これを試して、最初の行のみを検索するというアイデアを確認してください。結合してfind
ファイル名を取得し (できればフィルタリングも)、awk
最初の行をチェックしてファイル名と一緒に出力します。find | parallel 'perl -lane '\'' print "$ARGV: $_" if $. == 1 and /searchStr/i '\'' {}'
速度を上げるためのもう1つのアイデアは、利用可能なコアとスレッドを活用することです。GNU パラレルは です。この例では を使用していますが、上記とperl
同じ動作をします。コマンドの詳細は次のとおりです。awk
3.
find
現在のディレクトリとそのサブディレクトリ内のファイルを検索します。検索する別のディレクトリと、フィルタリングするファイル パターンまたは拡張子を指定できますfind /cygdrive/c/Directory/To/Search -iname "*.txt"
。|
「パイプ」、つまり結果のリストを次のコマンドに渡します。parallel
次のコマンドを並列に実行します。perl
テキスト ファイルの操作に優れたスクリプト言語で、置き換えたりsed
、することができますawk
。-lane
Perl ワンライナー用の便利なスイッチ セット。'\''
エスケープされたアポストロフィ。すでに の後にアポストロフィ セットが開始されているため必要ですparallel
。print "$ARGV: $_"
ファイル名 ($ARGV
)、コロン、スペース、および行全体 ($_
) を出力します。if
次の条件が満たされた場合にのみ、前の命令を実行します。$. == 1
行番号 ($.
) は 1 ( ) に等しい1
、つまりファイルの最初の行を参照していることになります。and
以下の条件も満たす必要があります。/searchStr/i
searchStr
検査対象の行には、大文字と小文字を区別せずにテキストが含まれています。'\''
もう一つのエスケープされたアポストロフィは命令の終わりを示しますperl
。{}
parallel
これは、 によって渡された各ファイル名に置き換えられますfind
。'
説明の終わりparallel
。
アップデート:アクションが最初の行のみにバインドされている場合でも、とawk
はperl
ファイル全体を読み取ります。解決策は、2 行目で明示的に詳細化を停止することです。
find -exec awk 'BEGIN {IGNORECASE=1} NR > 1 {exit} /searchStr/ {print FILENAME": "$0}' {} \;
find | parallel 'perl -lape '\'' exit if $. == 2; print "$ARGV: $_" if /searchStr/i '\'' {}'