Renaming a file in Bash using regular expressions

You don't actually need rename here, you can work around it:

$ file=35554842200284685106000166550020003504201637715423.xml
$ newname=$(sed -E 's/.*(.{48})/\1/'<<<"$file"); 
$ mv -v "$file" "$newname"
renamed '35554842200284685106000166550020003504201637715423.xml' -> '42200284685106000166550020003504201637715423.xml'

Here is one using bash specific P.E. parameter expansion.


Only mv for external tools

mv -v "$file" "${file:6}"


renamed '35554842200284685106000166550020003504201637715423.xml' -> '42200284685106000166550020003504201637715423.xml'

Keeping the last 48 chars would be.

mv -v "$file" "${file:(-48)}"

Your rename seems to be the useless one from util-linux.

You'd want to make sure one of the perl-based variants is installed instead (sometimes called prename) if you want to use regular expressions. And then:

rename -n 's:^\./\d+(?=\d{44}\.xml\Z)::' ./*.xml

(here replacing your 48 characters, with 44 digits followed by .xml so as to be more specific).

Alternatively, you could use zsh's zmv:

autoload zmv
zmv -n '[0-9]##([0-9](#c44).xml)' '$1'


zmv -n '<->.xml~^?(#c48)' '$f[-48,-1]'

(remove -n (dry-run) to actually do it).

Which also has the benefit of guarding against conflicts (two files having the same destination name)

With bash, you could do something like:

shopt -s extglob nullglob
for f in +([[:digit:]]).xml; do
  ((${#f) <= 48)) || echo mv -i -- "$f" "${f: -48}"