如何构建递归匹配 glob 的空格分隔、转义的文件完整路径?

如何构建递归匹配 glob 的空格分隔、转义的文件完整路径?

我有一个程序需要文件路径作为参数,该参数不能被引用并且不能依赖于工作目录。这可以在不链接多个xargs, tr, find, s 的情况下完成吗readlink

“*.csv”文件的输出示例:/home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv

答案1

为了将文件路径作为参数传递给命令,find自己做这件事-exec选项没有任何xargs诡计:

find /home/user -name '*.csv' -exec yourcommand '{}' +

这将找到调用的每个文件*.csv/home/user然后yourcommand /home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv ...将所有找到的文件作为参数执行。找到的每个文件都作为单独的完整参数传递给程序,因此不需要转义或其他任何内容:yourcommand获取许多参数,每个参数都是完整的文件路径。

另一种方法是一些 shell (zsh尤其)支持更高级的通配符,您可以在其中编写:

yourcommand **/*.csv

也能得到上面的效果。


如果您确实想要转义字符串本身,而不是直接运行命令,您可以使用bash's内置printf:

find /home/user -name '*.csv' -exec bash -c 'printf "%q " "$@"' dummy '{}' +

格式%q规范扩展为字符串参数的 shell 转义版本。对于许多参数,printf会重复所有参数的格式字符串,因此这会生成命令的所有参数的以空格结尾的转义字符串bash -cdummy用作 的值$0,并"$@"给出printf所有其余参数,即您的(完整)文件名。对于您的示例,这将准确输出/home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv.

答案2

zsh

print -r -- **/*.csv(D:a:q)

请注意,某些字符(如换行符、制表符或不可打印的字符)是用符号呈现的,$'...'这对您来说可能是个问题。

另一种方法是:

print -r -- *.csv(e/'REPLY=${(qq)REPLY:a}'/)

其中所有文件路径都用单引号引起来。

相关内容