9

I have a file named 35554842200284685106000166550020003504201637715423.xml and I simply need to rename it to 42200284685106000166550020003504201637715423.xml (remove everything before the last 48 characters). This simple regular expression (.{48}$) can extract the last 48 characters, but I can't make it work using rename in Bash.

How can I use rename and this regular expression to rename it to only the last 48 characters?

Edit:

Output of rename --help

[root@ip-000-00-0-000 tmp]# rename --help

Usage:
 rename [options] <expression> <replacement> <file>...

Rename files.

Options:
 -v, --verbose    explain what is being done
 -s, --symlink    act on the target of symlinks
 -n, --no-act     do not make any changes

 -h, --help     display this help and exit
 -V, --version  output version information and exit

For more details see rename(1).

Thank you.

devegili
  • 109

4 Answers4

18

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'
terdon
  • 242,166
15

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

file=35554842200284685106000166550020003504201637715423.xml

Only mv for external tools

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

Output

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

Keeping the last 48 chars would be.

mv -v "$file" "${file:(-48)}"
Jetchisel
  • 1,264
9

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'

Or

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}"
done
2
file=35554842200284685106000166550020003504201637715423.xml
rename  "s/"$file"/"${file: -48}"/" *.xml

rename --version:

/usr/bin/rename using File::Rename version 1.10
GAD3R
  • 66,769