我的情况:
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/pizza
和dir42/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
进一步阅读:
- read - 从标准输入读取一行(POSIX)