如何找出文件中就当前目录中不包含单词foo
(使用grep
)?
如何找出文件中就当前目录中不包含单词foo
(使用grep
)?
Answers:
如果您的grep具有-L
(或--files-without-match
)选项:
$ grep -L "foo" *
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
:^)在GNU grep中完成
-rL
而不是-L
匹配子目录
grep -L 'foo' -- *
标准是使用长选项的命令--
用于指示此点之后没有更多选项。
您可以单独使用grep来执行此操作(无查找)。
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”。然后,您将只获得匹配零行的文件。
问题
我需要重构一个大型项目,该项目使用.phtml
文件使用内联PHP代码写出HTML。我想改用Mustache模板。我想找到任何.phtml
不包含字符串的giles,new Mustache
因为它们仍然需要重写。
解
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
在每个匹配的路径上运行命令
格列普
-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没有任何-L选项。我确实找到解决此问题的方法。
这些想法是:
用diff命令区别2个转储文件。
grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
grep * *.log | cut -c1-14 | uniq > txt2.txt
diff txt1.txt txt2.txt | grep ">"
diff
在两个输出流之间进行a操作(我认为您在命令输出中用括号括起来,并且在某处也有尖括号),而不是转储文件名,如果您的系统支持的话,我想问题是,因为它不支持grep -L
正如@tukan所评论的那样,有一个关于-L
/ --files-without-matches
标志的针对Ag的公开错误报告:
由于错误报告的进展很少,因此,只要未解决该错误,就不要依赖-L
下面提到的选项。请改用此线程中介绍的不同方法。引用有关错误报告的评论[强调我的]:
有任何更新吗?
-L
完全忽略文件第一行上的匹配项。好像这不会很快解决,应该将标记完全删除,因为它实际上不能像广告中那样工作。
作为一种强大的替代方法grep
,您可以使用The Silver Searcher-Ag:
一个类似于ack的代码搜索工具,重点是速度。
查看man ag
,我们找到-L
或--files-without-matches
选项:
... OPTIONS ... -L --files-without-matches Only print the names of files that don´t contain matches.
即,要从当前目录中递归搜索不匹配的foo
文件:
ag -L foo
要仅在当前目录中搜索不匹配的文件foo
,只需指定--depth=0
递归即可:
ag -L foo --depth 0
-L
错误,此操作有时会失败-github.com/ggreer/the_silver_searcher/issues/238