grep 在许多目录中,但只查找每个目录的特定子目录,而不是所有子目录

grep 在许多目录中,但只查找每个目录的特定子目录,而不是所有子目录

我的情况:

dir1 
  subdir1
      FooFile
  subdir2

dir2 
  subdir1
      FooFile
  subdir2

因此,如果我cd dir1,我可以轻松地执行类似的操作find . | xargs grep "Foo",以列出包含Foo.

问题是子目录和文件太多,搜索需要很长时间。我想递归地进入每个主目录,然后专门进入一个子目录(subdir1),然后执行 grep。

Foo对我来说列出所有目录中包含的所有文件的名称的最佳方法是什么?对于每个不同名称的目录,subdir1总是比 低一级dir1,并且总是subdir1准确命名。

答案1

关于什么

grep "foo" */subdir1/*  */subdir1/.*

? (根据您当前的问题,这似乎符合要求。除非有太多“subdir1”子目录,以至于 shell 无法向 grep 提供整个列表。

如果您只想查看文件中是否出现“foo”,您可以添加 -q 并测试它是否以 0 退出

您还可以执行递归 grep,然后丢弃不需要的内容(大量 I/O,但很简单):

grep -r "foo" . | grep "^\./[^/][^/]*/subdir1/[^/][^/]*:"

(请参阅下面的注释:这里,即使名称包含“:”,这也会像您在 subdir1 下找到文件名一样工作,并且该文件确实包含 foo。不过,它可能会错过名称中包含换行符的文件,如在第二个 grep 中,它不会看到第一个“./firstleveldir/”名称,因此第二个 grep 将忽略它......)

答案2

如果你想看及以下所有(子)目录命名subdir1 为从顶层往下一层,你可以这样做

find */subdir1 …

如果您正在寻找以下文件名字包含Foo,你可以做

find */subdir1 -type f -name "*Foo*" -print

或者你可以这样做

find */subdir1 -type f -print | grep "Foo"

但这将包括每个文件在一个目录下 其名称包含字符串Foo,例如dir42/subdir1/Foods_I_Like/pizzadir42/subdir1/Foods_I_Like/chicken

如果您正在寻找文件包含 Foo (即,谁的内容包含Foo),你可以做

find */subdir1 -type f -print | xargs grep "Foo"

笔记:

  • 这是有效的,因为find的概要(用法)看起来像
    寻找[选项][初始点...][表达]
    即,您可以find在多个起点上调用一次;如:
    寻找   目录 1/子目录 1 目录 2/子目录 1 [表达]
  • 这可以很好地处理名称中包含空格的文件和目录。
  • 如果您正在寻找文件或目录其名称包含,从相应的命令中Foo省略。-type f
  • 当然必须引用"*Foo*",也不能引用*/subdir1。引用"Foo"是可选的 - 它不会造成伤害,但您不需要引用不包含任何特殊字符的单词。
  • 您可以省略-print,因为这是默认操作。

答案3

您可以使用脚本来完成此操作,例如

#!/bin/sh
find . -type d | while IFS= read -r pathname
do
    for name in "$pathname"/subdir1/*Foo*
    do
        [ -f "$name" ] && echo "$name"
    done
done

关于路径名中换行符的常见警告。用这棵树进行测试:

./dir2
./dir2/subdir1
./dir2/subdir1/FooFile
./dir2/subdir2
./subdir1
./subdir1/FooFile
./dir spacew
./dir spacew/subdir1
./dir spacew/subdir1/FooFile
./dir spacew/subdir2
./dir1
./dir1/subdir1
./dir1/subdir1/FooFile

制作的剧本

./subdir1/FooFile
./dir2/subdir1/FooFile
./dir spacew/subdir1/FooFile
./dir1/subdir1/FooFile

这个问题关于 的使用是不明确的grep(正如所写的,与 没有区别echo,除了使用正则表达式而不是 shell 通配符的可能性)。或者,您可以grep直接使用:

#!/bin/sh
find . -type f -name '*Foo*' | grep -E 'subdir1/Foo[^/]*$' | while IFS= read -r pathname
do
    echo "$pathname"
done

进一步阅读:

相关内容