0

I have a very peculiar problem, following an answer in Rename multiples files using Bash scripting I am trying to rename some files. This is the code I am using

#!/bin/bash
for file in *.HHZ_00; do mv $file ${file/${file:14:2}/00}; done

What I understand this to do is to replace the 2 characters following character index 14 (starting from zero) to 00.

I am using 2 subsets of files to test it, one is this

2018113154211.25.AGCC.HHZ_00
2018113154211.25.APAC.HHZ_00

When running the code these successfully rename to

2018113154211.00.AGCC.HHZ_00
2018113154211.00.APAC.HHZ_00

The second subset fails at this, this subset is

2018070220829.28.AGCC.HHZ_00
2018070220829.29.APAC.HHZ_00

These rename unsuccessfully to

2018070220829.00.AGCC.HHZ_00
2018070220800.29.APAC.HHZ_00

Notice how the indices 11 and 12 are changed for the second file, not the 14 and 15 as I want it to, very curiously now the SECOND time I run it, using the last files as input, I get

2018070220829.00.AGCC.HHZ_00
2018070220800.00.APAC.HHZ_00

This is partially successful, but now the second filename is ruined...what am I doing wrong? Is it because the 29 is repeating in these files?

If someone has a solution using the rename command that would be great too, I tried using it but I am unfamiliar with the syntax.

  • 2
    Yes it's because the characters repeat; ${file/${file:14:2}/00} replaces the first instance of whatever characters occur in positions 14-15 – steeldriver Jun 12 at 19:18
  • ... you could simply use "${file:0:14}00${file:16}" I think? – steeldriver Jun 12 at 19:22
  • You might find stackoverflow.com/questions/11809666/… helpful if you're comfortable with regex – einfeyn496 Jun 12 at 19:27
  • @steeldriver That's an answer in the comments. Let's turn it into a proper answer instead of just comment – Sergiy Kolodyazhnyy Jun 12 at 22:13
  • 1
    @SergiyKolodyazhnyy good point, converted to answer below – steeldriver Jun 13 at 0:30
1

Yes it's because the characters repeat; ${file/${file:14:2}/00} replaces the first instance of whatever characters occur in positions 14-15.

A simple way to do it in bash, without the nested parameter expansion, would be

$ for file in *.HHZ_00; do 
    echo mv "$file" "${file:0:14}00${file:16}"
  done
mv 2018070220829.28.AGCC.HHZ_00 2018070220829.00.AGCC.HHZ_00
mv 2018070220829.29.APAC.HHZ_00 2018070220829.00.APAC.HHZ_00
mv 2018113154211.25.AGCC.HHZ_00 2018113154211.00.AGCC.HHZ_00
mv 2018113154211.25.APAC.HHZ_00 2018113154211.00.APAC.HHZ_00

POSIXly, you could use %% and # (twice) to remove the longest suffix and shortest prefix respectively:

$ for file in *.HHZ_00; do 
    pfx="${file%%.*}"; rem="${file#*.}"; sfx="${rem#*.}" 
    echo mv "$file" "${pfx}.00.${sfx}"
  done
mv 2018070220829.28.AGCC.HHZ_00 2018070220829.00.AGCC.HHZ_00
mv 2018070220829.29.APAC.HHZ_00 2018070220829.00.APAC.HHZ_00
mv 2018113154211.25.AGCC.HHZ_00 2018113154211.00.AGCC.HHZ_00
mv 2018113154211.25.APAC.HHZ_00 2018113154211.00.APAC.HHZ_00

Remove the echo once you are satisfied that it is doing the right thing.

| improve this answer | |
0

@steeldriver explained it wonderfully, I corrected this by using

#!/bin/bash
for file in *.HHZ_00; do mv $file ${file/${file:13:4}/.00.}; done
| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.