
「labels」という名前のディレクトリがあり、その中に「cat」または「dog」、あるいはその両方のラベルが別々の行に書かれたテキスト ファイルがあります。labels
ディレクトリ内のファイルの内容は次のとおりです。
cat labels/1.txt
cat
cat labels/2.txt
dog
cat labels/3.txt
cat
dog
ラベル「cat」のみを含むファイルの名前を取得したいです。次のコマンドを試しました:
ls labels | grep -Rwl "cat"
labels/1.txt
labels/3.txt
しかし、このコマンドは、「cat」または両方を含むファイル名を返します。しかし、私の要件は、「cat」と「dog」の両方ではなく、「cat」のみを含むファイル名を取得することです。
同様に、「dog」のみを含むファイル名を取得しようとすると、同じ方法で検索すると、「dog」または両方のラベルを含むファイル名が返されます。
ls labels | grep -Rwl "dog"
labels/2.txt
labels/3.txt
答え1
を 2 回使用できますgrep
。a) を使用して を含むすべてのファイルを一覧表示しcat
、次に b) を使用して を含むファイルを除外しますdog
。-l
と を-L
それぞれ使用します。 は、-l
一致するファイル名と-L
一致のないファイル名を一覧表示します。
grep -L 'dog' $(grep -l 'cat' <list of files>)
見るman grep
:
-L, --一致しないファイル
通常の出力を抑制し、代わりに、通常は出力が印刷されない各入力ファイルの名前を印刷します。スキャンは最初の一致で停止します。
-l, --一致するファイル
通常の出力を抑制し、代わりに、通常出力が印刷される各入力ファイルの名前を印刷します。スキャンは最初の一致で停止します。
答え2
GNU およびgrep
(xargs
すでに-R
使用しているのはいずれにせよ GNUgrep
拡張機能ですが、-r
ここでは が推奨されます) を使用する場合:
grep -rwlZ cat labels/ | xargs -r0 grep -wL dog
少なくとも1つのcat
単語を含み、dog
単語を含まないファイルをリストします(言葉その文脈では「囲まれていない単語の文字"、単語の文字英数字とアンダースコアを含む)-w
に置き換えて-x
、内容全体がは cat
/ dog
.
答え3
「cat」は含まれているが「dog」は含まれていないファイルの名前を一覧表示したい場合は、find
と GNU (または の GNU 拡張であるため、ブロックをサポートするawk
その他の) を使用して、次のように実行してください。awk
ENDFILE
awk
$ find labels/ -type f -exec awk -v IGNORECASE=1 '
/\<cat\>/ { cat = 1 };
/\<dog\>/ { dog = 1 };
ENDFILE {
if (cat == 1 && dog == 0) {
print FILENAME
};
cat = 0;
dog = 0;
}' {} +
labels/file1.txt
perl
または、代わりに以下を使用することもできますawk
:
$ find labels/ -type f -exec perl -l -n -e '
$cat = 1 if m/\bcat\b/i;
$dog = 1 if m/\bdog\b/i;
if (eof) {
print $ARGV if ($cat && ! $dog);
$cat=0;
$dog=0;
}' {} +
labels/file1.txt
上記の awk と perl の両方のバージョンからの出力は、labels/
サブディレクトリ内の次のファイルを使用して生成されました。
$ tail labels/*
==> labels/file1.txt <==
cat
==> labels/file2.txt <==
dog
==> labels/file3.txt <==
cat
dog
labels/file1.txt
これは、「cat」を含み、「dog」を含まない唯一のファイルであるため、印刷される唯一のファイル名です。
答え4
for f in *; do diff -q <(sort -u "$f") <(echo cat) >/dev/null && echo "$f"; done