
我有一個名為“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」的檔案名,而不是同時包含「cat」和「dog」。
同樣,當我嘗試獲取僅包含“dog”的檔案的名稱時。如果我以相同的方式搜索,那麼它會返回包含“dog”或兩個標籤的檔案名稱。
ls labels | grep -Rwl "dog"
labels/2.txt
labels/3.txt
答案1
您可以使用grep
兩次:a) 列出所有帶有 的文件cat
,然後 b) 篩選出dog
包含 的文件。分別使用-l
和-L
,其中-l
列出匹配的文件名和-L
不匹配的文件名:
grep -L 'dog' $(grep -l 'cat' <list of files>)
看man grep
:
-L, --檔案不匹配
抑制正常輸出;相反,列印每個通常不會列印輸出的輸入檔案的名稱。掃描將在第一個匹配處停止。
-l, --帶匹配的文件
抑制正常輸出;相反,列印通常會列印輸出的每個輸入檔案的名稱。掃描將在第一個匹配處停止。
答案2
使用 GNUgrep
和xargs
(無論如何,-R
您已經使用的是 GNU擴展,儘管在那裡更好):grep
-r
grep -rwlZ cat labels/ | xargs -r0 grep -wL dog
將列出至少包含一個cat
單字且不包含dog
任何單字的檔案 (單字在這種情況下,意思是:「沒有被包圍單字字符「,單字字符是字母數字字元和底線)。替換-w
為-x
以搜尋其全部內容的行是 cat
/ dog
。
答案3
如果您想列出包含“cat”但不包含“dog”的文件的名稱,請嘗試使用find
和 GNU awk
(或任何其他awk
支援ENDFILE
區塊的文件,因為這是 的 GNU 擴充功能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