如何使用 grep
命令查找当前目录中不包含单词 foo
的文件?
如果你的grep命令带有-L
选项(或--files-without-match
):
$ grep -L "foo" *
你可以只使用grep来完成这个任务(而不需要使用find)。
grep -riL "foo" .
这是对grep
使用的参数进行说明。
-L, --files-without-match
each file processed.
-R, -r, --recursive
Recursively search subdirectories listed.
-i, --ignore-case
Perform case insensitive matching.
如果您使用小写字母的 l
,则会得到相反的结果(具有匹配项的文件)。 -l, --files-with-matches
Only the names of files containing selected lines are written
foo
的文件:find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep 0
grep '0$'
会匹配具有10行倍数的文件!您需要在结尾处使用grep ':0$'
来检查是否有明确的“:0”在行末。然后,您将只获得与零行匹配的文件。 - TrinitronX以下命令使用第二个grep
来排除需要find
过滤的svn
文件夹。
grep -rL "foo" ./* | grep -v "\.svn"
如果您使用Git,则此命令将搜索所有已跟踪的文件:
git grep -L "foo"
如果你在 .bashrc 中开启了子目录 globbing(shopt -s globstar
,参见 这里),你可以在跟踪的文件子集中进行搜索:
git grep -L "foo" -- **/*.cpp
实际上,您需要:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
为了完整起见,以下是ripgrep版本:
rg --files-without-match "pattern"
您可以与文件类型和搜索路径结合使用,例如:
rg --files-without-match -t ruby "frozen_string_literal: true" app/
问题
我需要重构一个使用.phtml
文件以内联PHP代码写出HTML的大型项目。我想改用Mustache模板。我想找到任何不包含字符串 new Mustache
的.phtml
文件,因为这些文件仍然需要重新编写。
解决方案
find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
说明
管道符之前:
查找
find .
从此目录开始递归查找文件
-iname '*.phtml'
文件名必须包含.phtml
(i
表示不区分大小写)
-exec 'grep -H -E -o -c 'new Mustache' {}'
在每个匹配路径上运行grep
命令
grep
-H
总是打印输出行的文件名头。
-E
将模式解释为扩展正则表达式(即强制grep行为像egrep)。
-o
仅打印匹配的行。
-c
仅将所选行的计数写入标准输出。
这将给我一个以.phtml
结尾的所有文件路径列表,并显示每个文件中字符串 new Mustache
出现的次数。
$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
第一个管道 grep :0$
将此列表过滤,只包括以 :0
结尾的行:
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
sed 's/..$//'
剥离每行的最后两个字符,只留下文件路径。$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml
我在使用
技术方面运气不错。grep -H -E -o -c "foo" */*/*.ext | grep ext:0
我尝试使用grep -v
,但只得到了所有没有"foo"的行。
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
来实现这一点 :^) - bufhag -L 'foo'
。 - bishop