我有数百万个文件以“损坏”的名称保存。扩展名已另存为_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_pdf
和file.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
为试运行)。