在 find 命令的 -exec 选项中分隔文件名和路径

jbe*_*ock 2 bash find

我正在努力进行转义和表达式评估。我正在尝试在find...-exec COMMAND结构中运行命令,其中COMMAND对一个文件进行操作并输出到标准输出。要COMMAND在命令行上正常使用它,我只需重定向到一个新文件,如下所示:

COMMAND inputfilename.md > outputfilename.md.conf
Run Code Online (Sandbox Code Playgroud)

这工作正常。但是,如果我想递归地遍历目录及其子目录中的所有文件,使用find -exec,我似乎无法弄清楚如何分隔文件名和路径,以便我可以正确重定向。例如,这会产生一个错误:

find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/{}.cong' \;
Run Code Online (Sandbox Code Playgroud)

因为{}扩展了整个文件路径。我已经尝试了basenameand 的各种组合dirname,但我似乎无法让它们进行评估(相反,我只得到字符串 'basename' 等)。例如,这不起作用,因为文本 'basename' 刚刚出现

find ./ *.md -not -path './/.git/*' -exec COMMAND  '{} > ~/wiki/newdirectory/''basename {}''.conf' \;
Run Code Online (Sandbox Code Playgroud)

(返回此错误:)'No such file or directory - .//newdirectory/README.md.conf > ~/wiki/newdirectory/basename .//newdirectory/README.md.conf'

任何帮助,将不胜感激。总结一下,目标是:

  1. 递归遍历匹配所有文件*.md的目录
  2. 在每次迭代中执行COMMAND inputfile.md > ~/newdirectory/inputfile.md.confwhereinputfile是相同的字符串。

谢谢!

Gil*_*il' 5

无论您做什么,您都需要调用一个 shell 来将命令输出重定向到一个位置取决于find结果的文件。

find ./ *.md -not -path './/.git/*' -exec sh -c 'COMMAND "$0" > ~/wiki/newdirectory/"${0##*/}.cong"' {} \;
Run Code Online (Sandbox Code Playgroud)

不要{}在 shell 脚本中替换。这并非在所有系统上都受支持,即使在它所在的地方,这通常也不起作用,因为它会将文件名视为一段 shell 语法,例如,调用的文件;rm -rf ~;.md会导致您删除所有文件。

${0##*/}使用纯字符串操作来获取文件的基本名称。您也可以使用$(basename -- "$0").