5

假设我想将一些jpg.jpg以结尾的文件名更改为仅以.jpg(在 bash 中)结尾,并且我想通过管道输出findto来做到这一点xargs

通过使用sed

find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | sed 's/jpg.jpg/.jpg/g')

但是,这不会jpg.jpg替换.jpg.mv

通过使用awk

find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | awk '{gsub(/jpg.jpg/,".jpg")}; 1')

这也没有任何替代。我错过了什么吗?

4

5 回答 5

5

我会通过编写一个接受文件名并进行重命名的脚本来做到这一点:

#!/bin/sh

for FILE
do
    mv $FILE `basename $FILE jpg.jpg`.jpg
done

该脚本很容易通过xargs.

如果您想将它粉碎到单个命令行上,您可以这样做,但通常不值得麻烦。

编辑:如果我必须在一个命令行上执行此操作,我可能会使用不同的技巧xargs:使用sed将输出find转换为 shell 脚本:

find . -iname '*jpg.jpg' | sed -e 's/\(.*\)jpg\.jpg$/mv & \1.jpg/' | sh

xargs能够分出更少孩子的优势被mv无论如何都需要反复跑步所击败。如果你真的需要这个优势,你需要一个像我的第一个选项这样的解决方案,但编码为perl可以执行多个rename()调用而无需分叉任何mv.

于 2012-10-31T22:00:47.373 回答
4

如果您的rename系统上有可用的命令,那么以下命令应该可以工作:

rename 's/(.*)jpg.jpg/$1.jpg/g' *jpg.jpg
于 2012-10-31T21:39:48.687 回答
3

$(...)运行 xargs 之前由 bash 评估,所以 xargs 只看到该表达式的输出,因为它当前是 mv 的第二个参数。

所以它相当于:

... | xargs -I % mv % %
于 2012-10-31T21:40:10.507 回答
2

我会为此使用 GNU 并行:

find . -iname '*jpg.jpg' | parallel mv {} {.}

{}替换为输入,{.}替换为输入减去最后一个扩展名。与 parallel 一起使用--dry-run以查看将要执行的操作。

编辑 - 应该处理 file1jpg.jpg

根据您在保持大小写方面的需要,这可以通过参数扩展或使用 GNU sed 来完成:

参数扩展:

find . -iname '*jpg.jpg' | parallel v={}\; mv '{}' '${v/jpg.jpg/.jpg}'    

使用 GNU sed:

find . -iname '*jpg.jpg' | parallel mv '{}' '$(echo {} | sed -r "s/jpg\\.(jpg)$/.\1/I")'
于 2012-10-31T22:33:48.400 回答
1

不需要xargsor find

for i in *jpg.jpg; do mv "$i" "$(echo $i | sed 's/jpg.jpg$/.jpg/')"; done

并且没有真正需要sedawk两者之一:

for i in $(find . -type f -name "*jpg.jpg"); do mv "$i" "${i/%jpg.jpg/.jpg}"; done

这是另一种方式:

find . -type f -name "*jpg.jpg" -exec bash -c 'mv $0 ${0/%jpg.jpg/.jpg}' {} \;
于 2012-10-31T21:55:30.677 回答