Remove characters from file names recursively

Meet the Perl rename tool:

$ rename -n -v  's/~[^.]+//' *~*
rename(ABCDEF~20160531-162719, ABCDEF)
rename(Letter to Client 27May2016~20160531-162719.pdf, Letter to Client 27May2016.pdf)

(online man page, also see this Q)

That regex says to match a tilde, as many characters that are not dots, but at least one; and to replace whatever matched with an empty string. Remove the -n to actually do the replace. We could change the pattern to ~[-0-9]+ to just replace digits and dashes.

Sorry, you said "recursively", so lets use find:

$ find -type f -name "*~*" -execdir  rename -n -v  's/~[-0-9]+//' {} +
rename(./ABCDEF~20160531-162719, ./ABCDEF)
rename(./Letter to Client 27May2016~20160531-162719.pdf, ./Letter to Client 27May2016.pdf)

Or just with Bash or ksh, though directories with ~ followed by digits will break this:

$ shopt -s extglob       # not needed in ksh (as far as I can tell)
$ shopt -s globstar      # 'set -o globstar' in ksh
$ for f in **/*~* ; do 
    g=${f//~+([-0-9])/}; 
    echo mv -- "$f" "$g" 
  done
mv -- ABCDEF~20160531-162719 ABCDEF
mv -- Letter to Client 27May2016~20160531-162719.pdf Letter to Client 27May2016.pdf

Again, remove the echo to actually do the rename.


In bash:

shopt -s globstar
for file in **/*~[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]*
do
  echo mv -- "$file" "${file/~[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]/}"
done

This finds all filenames (recursively) that match the date pattern (following a tilde), then echoes a sample mv command to rename them. The target of the mv command is the result of a bash parameter expansion that replaces any tilde-datestring text with nothing.

Tags:

Rename