查找最后一个字符“_”并将其替换为“.”递归地对文件名进行处理

查找最后一个字符“_”并将其替换为“.”递归地对文件名进行处理

我有数百万个文件以“损坏”的名称保存。扩展名已另存为_pdf.

我想要的是,递归地编辑所有这些扩展以按预期使用点。

find . -name '*_pdf' -type f -exec bash -c 'mv -- "$1" "${1//_/.}"' -- {} \;

我已经尝试过这个 bash 脚本,但它替换了所有用“.”创建的“_”,我只想要最后一个 _,如果继续使用常见扩展名(pdf、jpg、jpeg)。

答案1

它正在替换所有实例,_因为它${1//_/.}是全局的(${1/_/.}将是非全局的,但替换第一的匹配而不是最后一个)。

相反,您可以使用 POSIX${1%_*}${1##*_}删除最短后缀和最长前缀,然后重新加入它们:

find . -name '*_pdf' -type f -exec sh -c 'mv "$1" "${1%_*}.${1##*_}"' sh {} \;

或者

find . -name '*_pdf' -type f -exec sh -c 'for f do mv "$f" "${f%_*}.${f##*_}"; done' sh {} +

对于多个扩展:

find . \( -name '*_pdf' -o -name '*_jpg' -o -name '*_jpeg' \) -type f -exec sh -c '
  for f do mv "$f" "${f%_*}.${f##*_}"; done
' sh {} +

我删除了--选项结束分隔符 - 这里不需要它,因为find名称前面带有./.

-i如果给定目录中mv存在 afile_pdffile.pdf存在的风险,并且您希望有机会不破坏现有的file.pdf.

答案2

使用 perlrename工具:

find ... rename 's/_pdf$/.pdf/' {} +

您可以为不同的扩展单独运行它,或者一次替换多个“通用扩展”:

find ... rename 's/_(pdf|jpg|jpeg)$/.\1/' {} +

如果你没有perl rename,你可以使用其他rename工具

find ... rename '_pdf' '.pdf' {} +

答案3

强制zsh版本:

autoload zmv # best in ~/.zshrc
zmv -v '(**/)(*)_(pdf|jpg|jpeg)(#q.)' '$1$2.$3'

(#q.)限制为常规的文件就像find一样-type f(#qD.)如果您还想像这样重命名隐藏文件或隐藏目录中的文件,请更改为find-v用。。。来代替-n试运行)。

相关内容