将 xargs -I 与 sed 结合起来

将 xargs -I 与 sed 结合起来

我想使用 find 查找某些文件,然后使用 xargs 与 cp 和 sed 将这些文件移动到另一个文件夹并重命名。我知道如何循环执行此操作,但这不是我想要的。

我试过:

find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')

为什么这不起作用以及解决方案是什么?

答案1

尝试这个。它不需要xargs,只需find和。它不会更改任何文件,但是sedcopy将要打印用于复制文件的 shell 命令列表。因此,如果您喜欢它打印的命令,那么您可以再次运行它并删除最后一行#之前的内容sh -x,然后让 shell 执行命令。

find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
    s/^/'/                      # surround filename with single quotes
    s/$/'/
    h                           # save filename in the sed hold space
    s/ABC/XYZ/g                 # change filename
    H                           # append to hold space (separates with newline)
    g                           # get original and modified from hold
    s/\n/ /g                    # replace the newline with a space
    s/^/cp -i/                  # make it into a copy command
"  #| sh -x                     # optionally pipe to shell

xargs为什么这种方法比本例更好?因为除了每个文件所需的命令之外,此方法总共仅启动 3 个进程(findsed和)。shcp

要使用xargs,处理每个文件名将需要比单个所需cp命令更多的进程。

让 sed 的一次调用生成的效率要高得多全部命令cp,而不是为每个文件名调用一个新sed进程。

答案2

使用 GNU Parallel 看起来像这样:

find ${FOLDER} -iname "*${SOME_STRING}*" |
  parallel cp {} '{= s/ABC/XYZ/g =}'

{= =} 构造包含更改 $_ 的 Perl 表达式。

优点之一是 GNU Parallel 会做正确的事情,即使您有以下文件:

My brother's 12" records worth >100$.txt

或类似的恐怖:

touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"

相关内容