将存储在文件中的目录列表传递给 find 命令

将存储在文件中的目录列表传递给 find 命令

从目录及其子目录中,可以通过以下方式找到所有 .c 文件

find /user/home/me/tests/ -name \*\.c

现在,目录列表存储在文件“list_of_dir”中

/user/home/me/test1
/user/home/me/test2
/user/home/me/test3
...

如何将它们提供给 find 命令来查找它们及其子目录中的所有 .c 文件?

提前致谢。

编辑:我的默认 shell 是 tcsh。

答案1

如果文件中有一个以换行符分隔的目录列表list_of_dir,并且您希望find安全地将该列表传递给分词或者路径名扩展并且在不超过行长度限制的情况下,使用(这里假设其和选项xargs是 GNU 实现):-d-r

xargs -r -d'\n' -I{} find {} -name '*.c' <list_of_dir

为了真正安全,应该使用 NUL 分隔的目录列表,而不是换行符分隔的列表。如果list_of_dir0包含 NUL 分隔的目录列表,则使用:

xargs -r -0 -I{} find {} -name '*.c' <list_of_dir0

怎么运行的

  • -r告诉 xargs 不要运行,find除非目录列表非空。

  • -0告诉 xargs 在输入上期待一个以 NUL 分隔的列表。这是-d'\n'告诉 xargs 期望换行符分隔列表的更安全的替代方案。

  • -I{}告诉 xargs 将目录放入 find 命令中它看到{}字符的位置(一次一个,find将为每个目录运行一次调用)。

答案2

$ (echo /tmp; echo /var/tmp) > file
$ find $(cat file) -prune
/tmp
/var/tmp
$ 

然而!如果目录名称中有换行符,或者文件名列表对于execve(2)最大参数来说太长,那么这可能不是一个伟大的想法……tcsh您必须使用当今 bourne shell 不喜欢的反引号表格$(...)

% find `cat file` -prune
/tmp
/var/tmp
% 

尽管这又遇到了与伯恩炮弹下所遇到的所有相同的问题。

答案3

在 中tcsh,当您引用命令替换时,它会被拆分为每个非空行一个基础,这听起来正是你想要的,所以你可以这样做:

find -- "`cat list.txt`" -name '*.c'

在类似 POSIX 的 shell 中,您需要执行以下操作:

(set -o noglob; IFS='
'; find -- $(cat list.txt) -name '*.c')

达到同样的目的。

假设list.txt至少包含一个非空行(否则,根据实现find,您将收到一条错误消息或者它将在当前目录中查找)。

这还假设没有任何行以谓词开头-或不是find谓词(大多数谓词以( , , ...)find开头,但也有, , ... )。--ok-print-type!()

这还假设list.txt足够小以适合命令参数的最大大小。

另一种选择是使用xargs.

<list.txt sed 's/"/"\\""/g;s/.*/"&"/'|xargs tcsh -c 'find $argv:q -name "*.c"'

sed其中以 . 可以理解的格式引用每一行xargs

与上面的限制相同,只是它应该通过运行尽可能多的命令来解决参数数量的限制find以避免它,并且它假设 的内容list.txt是当前语言环境中的有效文本。某些xargs实现对任何参数的最大大小也有相当低的限制,该限制可能明显小于路径的最大大小。

答案4

另一种方法是使用以下代码:

(echo directory1 ; echo directory2 ; echo directory3) > file
for d in $(cat file); do find $d -name '*.c'; done

这会将目录名称放入文件中,使用目录名称运行查找并输出结果。撇号将处理文件名中的任何空格或保留字符。

相关内容