使用 find 命令添加到文件名前面

使用 find 命令添加到文件名前面

有没有办法仅使用 find 命令在文件名前面添加一个字符串?

这样:

201a.txt
201b.png
...

就变成这样了:

foo_201a.txt
foo_201b.png
...

这:

find . -name '201*' -execdir mv {} foo_{} \;

不起作用,因为该{}部分包含文件名中的前导./,因此尝试写入foo_./201*.

如果仅使用 find 无法做到这一点,那么将字符串添加到文件名的最可移植(阅读:仅 coreutils,没有 shell 脚本,最容易理解)的方法是什么?

答案1

不。但是该rename命令提供了一个简单的解决方案。

$ ls -1
201a.txt
201b.png
$ rename 201 foo_201 201*
$ ls -1
foo_201a.txt
foo_201b.png
$

答案2

怎么样

find . -name '201*' -execdir basename {} \; | xargs -I{} mv {} foo_{}

basename是由提供的coreutils,并且由于xargs是由提供的,因此findutils它应该至少与find -execdir它本身一样可移植。


或者,仅使用 POSIX shell 功能

find . -name '201*' -execdir sh -c 'mv "$1" "foo_${1#*/}"' sh {} \;

答案3

单独使用这是不可能的find,即使使用 GNU find 也是不可能的。 GNU find 可以打印删除命令行前缀并添加另一个前缀的文件,方法是使用-printf foo_%p代替-print,但是 没有任何类似的东西-exec

find -printf 'mv foo_%p …' | sh如果你喜欢危险地生活,你可以使用 , 。这只适用于“驯服”的文件名,如果文件名中有空格、引号和其他特殊字符,它会严重中断。所以不要这样做。)

执行此操作的标准方法(就像在任何 POSIX 系统上工作的方式一样,也是一种常见的方式)是调用 shell 来执行字符串操作。

find . -name '201*' -exec sh -c 'mv -- "$0" "${0%/*}/foo_${0##*/}"' {} \;

我不使用它,-execdir因为它是一个 GNU 扩展,而你要求可移植性。请注意,它{}作为参数传递给 shell。切勿在 shell 代码内部使用{}:不仅因为它不可移植,而且最重要的是因为它会导致文件名被解释为 shell 代码,如果文件名包含特殊字符,则会失败。

在现代 POSIX 系统(过去十年的任何系统)上,您可以通过批处理 shell 调用来稍微加快此命令的速度。

find . -name '201*' -exec sh -c 'for x do mv -- "$x" "${x%/*}/foo_${x##*/}"; done' sh {} +

或者,在 ksh、bash 或 zsh 中,您可以使用递归通配符而不是调用find.

set -o globstar # ksh only
shopt -s globstar # bash only
for x in **/201*; do
  mv -- "$x" "${x%/*}/foo_${x##*/}"
done

答案4

您可以使用星号 ( *) 来代替,它会删除该./部分:

find * -name '201*' -exec mv {} foo_{} \;  

相关内容