假设我想更改一些以 jpg.jpg
结尾的文件名以仅以 .jpg
结束(bash),我想通过将find
的输出输出到 xargs
:
使用sed
:
find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | sed 's/jpg.jpg/.jpg/g')
但是,这不会在mv
的目标文件中替换jpg.jpg
。
使用awk
:
find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | awk '{gsub(/jpg.jpg/,".jpg")}; 1')
这都不替代。我错过了什么吗?
我会通过编写一个获取文件名并重命名的脚本来做到这一点:
#!/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
。
如果您的系统上有rename
命令,则以下命令应起作用:
rename 's/(.*)jpg.jpg/$1.jpg/g' *jpg.jpg
$(...)
在运行XARGS之前通过Bash评估CC_20,因此Xargs只是看到该表达式的输出,因为它当前是MV的第二个参数。
因此,它等效于:
... | xargs -I % mv % %
我将与GNU并行同行:
find . -iname '*jpg.jpg' | parallel mv {} {.}
{}
被输入替换,{.}
被输入减去最后扩展名代替。并行使用--dry-run
,以查看将要做什么。
编辑 - 应处理file1jpg.jpg
根据保留案例的需求,可以通过参数扩展或使用GNU来完成:
参数扩展:
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")'
不需要xargs
或find
:
for i in *jpg.jpg; do mv "$i" "$(echo $i | sed 's/jpg.jpg$/.jpg/')"; done
,sed
或awk
实际上并不需要:
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}' {} ;