コマンド `grep -Ilri foo. | xargs grep -i bar`は、生成されたパスにスペースがない場合にのみ機能します。

コマンド `grep -Ilri foo. | xargs grep -i bar`は、生成されたパスにスペースがない場合にのみ機能します。

その単語を含むすべてのファイルfooとその単語を含むファイルを見つけるには、bar次のようにします。

grep -Ilri foo . | xargs grep -i bar

(大文字と小文字を区別せずにバイナリファイルを除外します。)... ただし、ファイルパスが次の場合

/Users/myusername/Text Files

それではうまくいきません。だから今xargs部品

grep -i bar /Users/myusername/Text Files

しかし実際にはそうする必要がある

grep -i bar "/Users/myusername/Text Files"

または

grep -i bar /Users/myusername/Text\ Files

どのように機能させるのですか? (macOS Montereyから)。

答え1

grepヌルバイトでファイル名を区切るGNUの-Z/オプションをサポートし--null(FreeBSDは長い--nullバリエーションのみをサポート)、ヌルバイトをxargs入力区切り文字として使用するオプション-0(一部あり)をサポートする場合は、それを使用してファイル名を--null安全に処理するできます。

grep -Ilri --null foo . | xargs -0 grep -i bar

grepそして、これらのxargs非標準オプションをサポートしていない場合(ただし、どちらも標準ではない-r)、-I次のものを使用できますfind

find . -type f -exec grep -Iiq foo {} \; -exec grep -iq bar {} \; -print

現在のディレクトリから始まるファイルを探し、見つかったファイルごとにgrep「foo」が含まれているかどうかを確認するgrepために実行されます。その名前。

これは非常に効率的ではありませんが、安全に機能します。

答え2

fooUnixシステムでPOSIXツールを強制的に「該当する単語とその中の単語を含むすべてのファイルを検索する」(テストされていません):bar

find . -type f -exec \
    awk '
        FNR==1 { x=y=0 }
        { $0 = tolower($0) }
        /foo/ { x=1 }
        /bar/ { y=1 }
        x && y { hits[FILENAME]; nextfile }
        END { for (fname in hits) print fname }
    ' {} +

または必要に応じて:

find . -type f -exec \
    awk '
        FNR==1 { x=y=0 }
        { $0 = tolower($0) }
        /foo/ { x=1 }
        /bar/ { y=1 }
        x && y && !seen[FILENAME]++ { print FILENAME; nextfile }
    ' {} +

上記のいずれの場合も、効率性のためにこれをサポートするawkを使用しますがnextfile、サポートしていないawkでも同じファイル名を複数回印刷しないようにコードを記述します。

上記は、部分文字列や正規表現と文字列の一致に興味がないと仮定しています。

関連情報