如何使用 xargs 中的参数来计算另一个表达式?

如何使用 xargs 中的参数来计算另一个表达式?

我想评估basename给定参数的表达式xargs

我测试过:

find . -name '*.txt' | xargs -I f cp f DIR_OUT/copied_$(basename f)

这是no file or directory因为$(basename f)没有正确评估。

我可以将其分为两个步骤:复制和更改文件名,但我想学习如何使用xargs.

答案1

在命令启动之前,您在命令中使用的命令替换$(basename f)将仅被评估一次(产生字符串f) 。xargs这就是您的代码无法将文件复制到正确名称的原因。

您收到的“没有这样的文件或目录”错误是由于finDIR_OUT/copied_f被替换为 找到的文件的路径名find


做同样事情的更稳健的方法,

find . -type f -name '*.txt' -exec sh -c '
    for pathname do
        cp "$pathname" "DIR_OUT/copied_${pathname##*/}"
    done' sh {} +

或者,xargs同时注意在find和之间传递找到的路径名xargs作为以 null 结尾的字符串:

find . -type f -name '*.txt' -print0 |
xargs -0 sh -c '
    for pathname do
        cp "$pathname" "DIR_OUT/copied_${pathname##*/}"
    done' sh

在这两种变体中,我们调用一个小的内联 shell 脚本,该脚本循环遍历给定的路径名​​并将它们复制到目录下的新名称DIR_OUT。可以${pathname##*/}替换为$( basename "$pathname" ).

请注意,-print0(in find) 和-0(in xargs) 是非标准的,但通常实现。

有关的:

答案2

您需要对原始命令进行一些小修改

find . -name '*.txt' | xargs -I f sh -c 'cp f DIR_OUT/copied_$(basename f)'

答案3

要解释$(),您需要从 运行 shell xargs

这里

您还应该使用 find 的空分隔输出(当系统允许时),以防止文件名中出现有问题的字符。

这应该做你想要的:(如果某个地方没有空支持,请-0从 中删除xargs并替换-print0-print

find . -type f -name '*.txt' -print0 | xargs -n1 -r0 /bin/sh -c 'cp "$1" "DIR_OUT/copied_$(basename "$1")"' ''

-type f确保 find 只给出文件结果 -print0make find 打印 null 终止的输出 -n1确保xargs仅将一个结果传递给进程 -r告诉xargs如果没有结果则不要运行内容 -0makexargs接受 null 终止的输入

运行的命令是一个带有内联脚本和一个空白参数的 shell(因为这就是参数传递给-c脚本的方式)

xargs将参数传递给sh -c 'commands' '',这会导致第一个参数位于$1-c 内。单引号阻止调用 shell 处理$()and $1

相关内容