名前にtxt
スペースや特殊文字(例:#
。
があるが存在しないすべての項目を一覧表示するgrep
ソリューションがあります。grep -L "cannot have" $(grep -l "must have" *.txt)
must have
cannot have
abc defg.txt
たとえば、1行だけを含むファイルがありますmust have
。
したがって、通常、grepソリューションはを見つける必要がありますabc defg.txt
が、次のように返します。
grep: abc: No such file or directory
grep: defg.txt: No such file or directory
含まれているファイル名については、#
grepソリューションが機能しないと思います。
誰でもgrepソリューションを修正するのに役立ちますか?
答え1
もしさらに進みたい場合は、awkを使用して一度にすべての操作を実行できます。
awk 'function s(){if(a&&!b){print f}} FNR==1{s();f=FILENAME;a=b=0}
/must have/{a=1} /cannot have/{b=1} END{s()}' filepattern
最近のgawkでは、BEGINFILEとENDFILEを使用して単純化できます。 (すべてのawk回答と同様に、-fを使用してawkコマンドをファイルに入れることができ、ほとんどの場合と同様に、必要に応じて簡単にPerlに変換できます。)
答え2
すでにGNU固有のオプション()を使用しているので、-L
次のことができます。
grep -lZ -- "must have" *.txt | xargs -r0 grep -L -- "cannot have"
アイデアは、-Z
NULで区切られたファイル名のリストを印刷し、xargs -r0
そのリストを2番目のgrep
。
デフォルトでは、コマンド置換はスペース、タブ、および改行(およびではNUL)にzsh
分割されます。 Bourneなどのシェルは、zsh
分割によって引き起こされる各単語に対してワイルドカード操作も実行します。
次のことができます。
IFS='
' # split on newline only
set -f # disable globbing
grep -L -- "cannot have" $(
set +f # we need globbing for *.txt in this subshell though
grep -l -- "must have" *.txt
)
ただし、これにより改行文字を含むファイル名が壊れ続けます。
zsh
(そして唯一)では、zsh
次のことができます。
IFS=$'\0'
grep -L -- "cannot have" $(grep -lZ -- "must have" *.txt)
または:
grep -L -- "cannot have" ${(ps:\0:)"$(grep -lZ -- "must have" *.txt)"}
答え3
代わりにシェルコマンドを試してくださいfind
。grep
find . -name '*.txt' -print0 | xargs -0 -I{} sh -c 'grep -q "must have" -- "{}" && grep -L "cannot have" -- "{}"'