0

I have following set of files

top_axi_256_wrapper_05.02.01.14.00_sample06.tgz
top_axi_128_wrapper_05.02.01.14.00_sample06.tgz

I want to replace 05.02.01.14.00 part with 05_02_01_14_00. So the final output is the following renamed files

top_axi_256_wrapper_05_02_01_14_00_sample06.tgz
top_axi_128_wrapper_05_02_01_14_00_sample06.tgz

My directory may contain following type of file names too.

a72_a_0.0.0_0.00.04_ac_dc.tgz

Here , I wish to rename the file to

a53_1c_256K_a_0_0_0_0_00_04_ac_dc.tgz

How to do this?

2
  • The last example doesn't make sense.
    – choroba
    May 17, 2016 at 7:34
  • Well, partly yes, I was trying to simply emphasize that I want to replace all the dots with dashes except for the extension one (.tgz) May 17, 2016 at 7:36

2 Answers 2

2

You basically want to replace a dot by an underscore except for the last one.

You can use bash's parameter expansion for that:

for file in * ; do
    replace_all=${file//./_}
    newname=${replace_all%_*}.${replace_all##*_}
    mv "$file" "$newname"
done
  • //./_ means replace all dots by underscores
  • %_* means remove everything after the last underscore
  • ##*_ means remove everything up to the last underscore

Or you can first save the extension, then remove it, replace all dots by underscores, and add the extension back. Left as an exercise for the reader.

1
  • Thanks a lot. Bash parameter expansion is new to me and I am liking it. Thanks a lot for introducing this to me. May 17, 2016 at 7:58
1

The perl-based rename utility can use any perl statements to rename files, not just the s/// search-and-replace operator or the y// translation operator (just make sure you set $_ to whatever you want the file to be renamed to).

From man rename:

"rename" renames the filenames supplied according to the rule specified as the first argument. The perlexpr argument is a Perl expression which is expected to modify the $_ string in Perl for at least some of the filenames specified. If a given filename is not modified by the expression, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input.

For example:

rename 'my($b,$e) = m/^(.*)\.([^.]+)$/; $b =~ s/\./_/g; $_="$b.$e"' files

This splits the filenames into base name ($b) and extension ($e). $b then has all periods (.) replaced with underscores. Finally, $_ is set to "$b.$e".

Output (with the -v verbose option):

$ touch top_axi_256_wrapper_05.02.01.14.00_sample06.tgz \
    top_axi_128_wrapper_05.02.01.14.00_sample06.tgz \
    a72_a_0.0.0_0.00.04_ac_dc.tgz

$ rename -v 'my($b,$e) = m/^(.*)\.([^.]+)$/; $b =~ s/\./_/g; $_="$b.$e"' *
a72_a_0.0.0_0.00.04_ac_dc.tgz renamed as a72_a_0_0_0_0_00_04_ac_dc.tgz
top_axi_128_wrapper_05.02.01.14.00_sample06.tgz renamed as top_axi_128_wrapper_05_02_01_14_00_sample06.tgz
top_axi_256_wrapper_05.02.01.14.00_sample06.tgz renamed as top_axi_256_wrapper_05_02_01_14_00_sample06.tgz

BTW, use -n while testing your rename statements. More from man rename:

-n, -nono

No action: print names of files to be renamed, but don't rename.

perl rename is available packaged for most distros (e.g. the rename package in Debian), or from https://metacpan.org/release/File-Rename

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .