2

I got the following problem: I want to rename files in the format of 12xy[..].log to [...].log.

My problem is, that some of them have an a following the first time and some of them got a v - so I cannot use commands, that follow the logic of replacing part of the name up to a certain character. (Like an underscore etc.)

Is there anyway to rename them quickly?

Edit: There is always the same prefix of MD18. So for example there are some files named MD18v230_SHAPE.log or another one named MD18a004_FACES.log and so forth. I would like to have them named v230_SHAPE.log and a004_FACES.log.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

3 Answers3

3

I'd use tools designed for batch renaming as they're good at making sanity checks before doing anything or have dry-run modes that show you what they would do instead of doing them.

There are several of them, the most popular ones being perl's rename, a very short example script that used to be shipped with perl since the 80s but has still evolved into something more advanced (and several variants thereof). That one can use all the power of perl's string processing capabilities, so the possibilities are endless.

There's also an unrelated but very limited command called rename in the util-linux package.

mmv is a dedicated batch renaming tool, also from the 80s. It used to be quite popular but seems to have fallen out of fashion lately.

zsh comes with a zmv auto-loadable function that can use the full power of zsh filename generation and expansion operators.

Here, your task is relatively trivial as it's just a matter of removing the first 4 characters of files that start with MD18, so:

rename 's/^MD18//' MD18*.log
mmv 'MD18*.log' '#1.log'
autoload zmv
zmv 'MD18(*.log)' '$1'

You can also always use a loop in simpler shells like bash:

for file in MD18*.log; do
  mv -i "$file" "${file#MD18}"
done

But it won't have any of the safeguards of the specialised tools. Here we're still using -i though to give a chance to the user to abort before a file is lost/overridden in the process. A dry run can also be performed by prepending the command with echo.

  • you coud improve the for loop with cp instead mv, cp can create hard links and auto rename with suffix in case of collision – alecxs Aug 24 '21 at 12:12
1

Do all these filenames start with 12xy or do you want to remove the first 4 characters of the filename, whatever they be? Are all your filenames like these - 12xy_lmn.log, 12xydef.log, 12xyabc.log, 12xyvw.log, ...?

If so, you could rename using a for loop:

for fn in ./12xy*.log 
do
    mv -i "$fn" "$(sed -e 's/^12xy//' <<< "$fn")"
done

You may change "mv -i" to "mv", if you are okay with collisions.

If, however, you want to remove the first 4 characters in the filename, whatever they are, use:

for fn in ./*.log 
do
    mv -i "$fn" "$(sed -e 's/^....//' <<< "$fn")"
done
ilkkachu
  • 138,973
Johnny
  • 19
0
for file in /path/to/MD18*.log; do
    name=$(echo "$file" | sed -E 's/.{4}(.*)/\1/')
    mv "$file" "$name"
done

This will remove the first 4 characters.

sseLtaH
  • 2,786
  • 2
    ${file#????} would be more efficient and safer than piping the unquoted $file expansion through sed. Also, since you may not want to change every file's name jest because the start with M, you may want to remove the MD18 prefix explicitly with ${file#MD18}. This is however already mentioned by Stéphane in their answer. – Kusalananda Aug 24 '21 at 11:48