Unfortunately, the method you tried is more complex than it needs to be, and fragile (it breaks if file names contain certain special characters). Here's a simpler method relying on parameter expansion to transform the file name:
for f in *; do mv -v -- "$f" "${f/./_}"; done # replace the first .
for f in *; do mv -v -- "$f" "${f//./_}"; done # replace every .
This requires bash, ksh or zsh as the shell: other shells such as dash (which is Ubuntu's /bin/sh
, so commonly used for scripting, but hardly ever used interactively) don't have the ${VARIABLE/PATTERN/REPLACEMENT}
form of parameter expansion.
Alternatively, you can use prename
(apt install rename
):
rename 's/\./_/' * # replace the first .
rename 's/\./_/g' * # replace every .
Alternatively, you can use zsh's zmv:
autoload -U zmv # put this in your .zshrc
zmv '*' '${f/./_}' # replace the first .
zmv -W '*.*.*' '*_*.*' # replace the next-to-last .
zmv '*' '${f//./_}' # replace every .
All the snippets in my answer skip files whose name begins with a dot.
rename
command (the Larry Wall one).