我想将正则表达式与 Linux 的find
命令一起使用,以递归地进入一个庞大的目录树,向我显示所有 .c、.cpp 和 .h 文件,但忽略包含某些子字符串的匹配项。最终,我想将输出发送到一个xargs
命令,以便对所有匹配的文件进行某些处理。我可以find
通过 grep 管道输出以删除包含这些子字符串的匹配项,但该解决方案不适用于包含空格的文件名。所以我尝试使用find
's -print0 选项,它以 nul 字符而不是换行符(空格)来终止每个文件名,并使用xargs -0
期望以 nul 分隔的输入而不是以空格分隔的输入,但我不知道如何通过 nul 分隔find
成功通过管道 grep 过滤器;grep -Z 在这方面似乎没有帮助。
所以我想我会写一个更好的正则表达式find
并取消中间grep
过滤器......也许sed
会是一个替代方案?
无论如何,对于以下目录的小样本...
./barney/generated/bam bam.h
./barney/src/bam bam.cpp
./barney/deploy/bam bam.h
./barney/inc/bam bam.h
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
...我希望输出包括所有 .h、.c 和 .cpp 文件,但不包括那些出现在“生成”和“部署”目录中的文件。
顺便说一句,您可以创建一个完整的测试目录(名为 fredbarney),通过将整行剪切并粘贴到您的 bash shell 中来测试该问题的解决方案:
mkdir fredbarney; cd fredbarney; mkdir fred; cd fred; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > inc/dino.h; echo x > docs/info.docx; echo x > generated/dino.h; echo x > deploy/dino.h; echo x > src/dino.cpp; cd ..; mkdir barney; cd barney; mkdir inc; mkdir docs; mkdir generated; mkdir deploy; mkdir src; echo x > 'inc/bam bam.h'; echo x > 'docs/info info.docx'; echo x > 'generated/bam bam.h'; echo x > 'deploy/bam bam.h'; echo x > 'src/bam bam.cpp'; cd ..;
此命令查找所有 .h、.c 和 .cpp 文件...
find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$"
...但是如果我通过 xargs 管道输出其输出,则每个“bam bam”文件都会被视为两个单独的(不存在的)文件名(请注意,这里我只是ls
用作我实际想要做的事情的替身输出):
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" | xargs -n 1 ls
ls: ./barney/generated/bam: No such file or directory
ls: bam.h: No such file or directory
ls: ./barney/src/bam: No such file or directory
ls: bam.cpp: No such file or directory
ls: ./barney/deploy/bam: No such file or directory
ls: bam.h: No such file or directory
ls: ./barney/inc/bam: No such file or directory
ls: bam.h: No such file or directory
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
所以我可以使用 -print0 和 -0 参数来增强它find
和xargs
:
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | xargs -0 -n 1 ls
./barney/generated/bam bam.h
./barney/src/bam bam.cpp
./barney/deploy/bam bam.h
./barney/inc/bam bam.h
./fred/generated/dino.h
./fred/src/dino.cpp
./fred/deploy/dino.h
./fred/inc/dino.h
...这很好,除了我不希望输出中出现“生成”和“部署”目录。所以我试试这个:
$ find . -regextype posix-egrep -regex ".+\.(c|cpp|h)$" -print0 | grep -v generated | grep -v deploy | xargs -0 -n 1 ls
barney fred
...这显然不起作用。所以我尝试将 -Z 选项与 grep 一起使用(不确切知道 -Z 选项的真正作用),但这也不起作用。所以我想我会写一个更好的正则表达式find
,这是我能想到的最好的:
find . -regextype posix-egrep -regex "(?!.*(generated|deploy).*$)(.+\.(c|cpp|h)$)" -print0 | xargs -0 -n 1 ls
...但是 bash 不喜欢那样(!。*:未找到事件,无论这意味着什么),即使这不是问题,我的正则表达式似乎也不能在我通常的正则表达式测试器网页上工作采用。
有什么想法可以让我完成这项工作吗?这是我想要的输出:
$ find . [----options here----] | [----maybe grep or sed----] | xargs -0 -n 1 ls
./barney/src/bam bam.cpp
./barney/inc/bam bam.h
./fred/src/dino.cpp
./fred/inc/dino.h
...而且我想避免使用脚本和临时文件,我想这可能是我唯一的选择。
提前致谢!-标记