grep当前目录下所有.h和.c文件中的关键字,但不包括两个目录

 小老虎颖儿 发布于 2023-02-07 10:50

我希望到grep中的所有关键字.h.c文件的当前目录下./,但不包括两个目录./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.我的问题是:find命令的选项有从左到右的执行顺序?

    有没有更简洁的方法来实现我的目标:grep一个关键字在所有.h.c当前目录下的文件,但排除两个目录?

Jonathan Lef.. 6

    -o运营商是"或"操作.在-o第二路径后后它需要另一个测试.括号表达式经受的条件-type d-prune太.总的来说,该术语表示'如果当前名称是目录,并且路径与路径表达式匹配,那么搜索将被修剪',这意味着搜索不会继续

    一般操作find是它搜索目录列表,并对搜索表达式求值为true的目录下找到的每个名称执行某些操作.

    您当前的命令是:

    find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -o -regex '.*\.\(h\|c\)$' -print
    

    我要放弃这find .部分,假设其余的答案.我还打算使用的名称AB到位的stubdom,并dist缩短它使一切都可见.

    我们可以通过更换肯定简化它-regex具有-name:

    -type d \( -path "./A/*" -o -path "./B/*" \) -prune -o -name '*.[ch]' -print
    

    请注意,条件之间的默认连接是'和'.使用C或壳符号&&||,我们可以看到的是,表达的形式为:

    (-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 {} +

如果任何文件名或目录名包含空格(或制表符或换行符),则可以避免出现问题.如果你的这些命令的版本支持表示法(GNU的话,那么你也可以使用-print0术语in find-0选项来解决这个xargs问题; Mac OS X也是如此,因此也可能是其他BSD变体).

(使用系统(BSD)在Mac OS X 10.9.1上进行测试find,而不是使用GNU进行测试find.)

1 个回答
    1. -o运营商是"或"操作.在-o第二路径后后它需要另一个测试.括号表达式经受的条件-type d-prune太.总的来说,该术语表示'如果当前名称是目录,并且路径与路径表达式匹配,那么搜索将被修剪',这意味着搜索不会继续

      一般操作find是它搜索目录列表,并对搜索表达式求值为true的目录下找到的每个名称执行某些操作.

      您当前的命令是:

      find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -o -regex '.*\.\(h\|c\)$' -print
      

      我要放弃这find .部分,假设其余的答案.我还打算使用的名称AB到位的stubdom,并dist缩短它使一切都可见.

      我们可以通过更换肯定简化它-regex具有-name:

      -type d \( -path "./A/*" -o -path "./B/*" \) -prune -o -name '*.[ch]' -print
      

      请注意,条件之间的默认连接是'和'.使用C或壳符号&&||,我们可以看到的是,表达的形式为:

      (-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 {} +
    

    如果任何文件名或目录名包含空格(或制表符或换行符),则可以避免出现问题.如果你的这些命令的版本支持表示法(GNU的话,那么你也可以使用-print0术语in find-0选项来解决这个xargs问题; Mac OS X也是如此,因此也可能是其他BSD变体).

    (使用系统(BSD)在Mac OS X 10.9.1上进行测试find,而不是使用GNU进行测试find.)

    2023-02-07 10:51 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有