Replacing dots in file name with underscores except the extension

command linemvrename

Can someone suggest on how to rename the file name:

head.body.date.txt

To:

head_body_date.txt

Is there a single line statement to do the rename in Unix?

Best Answer

Iterate over the filenames, and use Parameter expansion for conversion:

for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done

The parameter expansion pattern, ${f//./_} replaces all .s with _s in the filename ($f).

The above will do a dry-run, to let the actual renaming take place, remove echo:

for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done

If you want to deal with any extension, not just .txt:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     echo mv -i -- "$f" "${pre//./_}.${suf}"; done

After checking remove echo for actual action:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     mv -i -- "$f" "${pre//./_}.${suf}"; done

Generic, for arbitrary number of dots, at least one:

for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
                 mv -i -- "$f" "${pre//./_}.${suf}"; done