我想使用 find 查找某些文件,然后使用 xargs 与 cp 和 sed 将这些文件移动到另一个文件夹并重命名。我知道如何循环执行此操作,但这不是我想要的。
我试过:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
为什么这不起作用以及解决方案是什么?
答案1
尝试这个。它不需要xargs
,只需find
和。它不会更改任何文件,但是sed
copy
将要打印用于复制文件的 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 个进程(find
、sed
和)。sh
cp
要使用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)')"