It's replacing all instances of _
because ${1//_/.}
is global (${1/_/.}
would be non-global, but replace the first match rather than the last).
Instead you could use POSIX ${1%_*}
and ${1##*_}
to remove the shortest suffix and longest prefix, then rejoin them:
find . -name '*_pdf' -type f -exec sh -c 'mv "$1" "${1%_*}.${1##*_}"' sh {} \;
or
find . -name '*_pdf' -type f -exec sh -c 'for f do mv "$f" "${f%_*}.${f##*_}"; done' sh {} +
For multiple extensions:
find . \( -name '*_pdf' -o -name '*_jpg' -o -name '*_jpeg' \) -type f -exec sh -c '
for f do mv "$f" "${f%_*}.${f##*_}"; done
' sh {} +
I removed the --
end-of-options delimiter - it shouldn't be necessary here since find
prefixes the names with ./
.
You may want to add a -i
option to mv
if there's risk that both a file_pdf
and file.pdf
exist in a given directory and you want to be given a chance not to clobber the exising file.pdf
.