我想在当前目录.h
下的所有.c
和./
文件中grep一个关键字,但在输出中排除两个目录./stubdom
和./dist
。
我搜索,尝试和测试了几个命令;最后,我认为一种 shell 有效:
find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -o -regex '.*\.\(h\|c\)$' -print | xargs grep map_foreign_range
此Shell查找所有.h和.c文件,并排除./stubdom/和./dist路径:
find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -regex '.*\.\(h\|c\)$' -print | xargs grep map_foreign_range
但是,以上命令不起作用!
(我在正则表达式之前删除了-o以获得AND操作!)
但是,我不太明白为什么会这样。我有几个问题:
\( -path "./stubdom/*" -o -path "./dist/*" \)
这是find的操作,但是它如何工作?以及为什么它不是\( -path "./stubdom/*" -o -path "./dist/*" -o \)
(我在末尾添加了另一个-o)。 -regex
放在-type
之前,它将打印出.o文件,这意味着如果将-regex
放在-type
之前,则.h
不起作用。我的问题是:
find命令的选项的执行顺序是从左到右?
.c
和ojit_code文件中使用关键字,但排除两个目录? 最佳答案
-o
运算符是“或”运算符。第二条路径之后的-o
在它之后需要另一个测试。带括号的表达式也受-type d
和-prune
条件的约束。总体而言,该术语表示“如果当前名称是目录,并且如果路径与任何路径表达式匹配,那么将修剪搜索”,这意味着搜索不会继续find
的一般操作是搜索目录列表,并对在搜索表达式计算为true的目录下找到的每个名称执行某些操作。您当前的命令是:
find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -o -regex '.*\.\(h\|c\)$' -print
我将删除
find .
部分,将其作为其余答案的假设。我还将使用名称A
和B
代替stubdom
和dist
来缩短它,以便一切都可见。我们当然可以通过将
-regex
替换为-name
来简化它:-type d \( -path "./A/*" -o -path "./B/*" \) -prune -o -name '*.[ch]' -print
请注意,条件之间的默认连接词是“和”。使用C或shell表示法
&&
和||
,我们可以看到表达式的形式为:(-type d && ( ... ) && -prune) || (-name '*.[ch]' && -print)
当您将
-regex
(现在为-name
)移到-type
之前时,您将表达式重写为:(-name '*.[ch]' && -type d && ( ... ) && -prune) || (-print)
因此,出现目标文件名的原因是无条件应用打印。
/*
条款上的-path
适得其反。 为了演示,创建一个垃圾目录,在其中添加
cd
并运行:mkdir a b c d
for d in a b c d
do
for file in abc def pqr zyz
do
for ext in c h
do cp /dev/null $d/$file.$ext
done
done
done
现在运行:
find . -name '*.[ch]' | wc -l
这给出了答案32。
现在运行:
find . -type d \( -path "./a/*" -o -path "./b/*" \) -prune -o -name '*.[ch]' -print | wc -l
这也给出32。
删除
/*
操作数的-path
部分,您将获得16。删除wc
将显示16个名称是c
和d
下的文件,它们是需要的文件。find . -type d \( -path "./a" -o -path "./b" \) -prune -o -name '*.[ch]' -print
因此,应用于您的方案,您应该能够使用:
find . -type d \( -path "./stubdom" -o -path "./dist" \) -prune -o -name '*.[ch]' -print
但是,您最好还是完全避免
xargs
:find . -type d \( -path "./a" -o -path "./b" \) -prune -o -name '*.[ch]' \
-exec grep map_foreign_range {} +
如果任何文件名或目录名包含空格(或制表符或换行符),则可以避免问题。您还可以使用
-print0
中的find
术语和-0
的xargs
选项来解决此问题,如果您的这些命令的版本支持该表示法(GNU会支持该表示法,那么Mac OS X也是如此,因此也可能支持其他BSD变体)。(在Mac OS X 10.9.1上使用系统(BSD)
find
进行了测试,而不是使用GNU find
进行了测试。)关于regex - grep当前目录下所有.h和.c文件中的关键字,但排除两个目录,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20871845/