How to rename a file using regex capture group in Linux? [duplicate]
Asked Answered
H

4

7

I want to rename a_1.0.tgz to b_1.0.tgz, since 1.0 may be changed to any version number, how can I achieve that?

For example, I can use mv a*.tgz b.tgz if I don't need to keep the version number.

Hindi answered 12/7, 2016 at 9:7 Comment(1)
For the record, mv a*.tgz b.tgz only works correctly if a*.tgz matches exactly one file.Evzone
K
14

zsh comes with the utility zmv, which is intended for exactly that. While zmv does not support regex, it does provide capture groups for filename generation patterns (aka globbing).

First, you might need to enable zmv. This can be done by adding the following to your ~/.zshrc:

autoload -Uz zmv

You can then use it like this:

zmv 'a_(*)' 'b_$1'

This will rename any file matching a_* so, that a_ is replaced by b_. If you want to be less general, you can of course adjust the pattern:

  • to rename only .tgz files:

    zmv 'a_(*.tgz)' 'b_$1'
    
  • to rename only .tgz files while changing the extension to .tar.gz

    zmv 'a_(*).tgz' 'b_$1.tar.gz'
    
  • to only rename a_1.0.tgz:

    zmv 'a_(1.0.tgz)' 'b_$1'
    

To be on the save side, you can run zmv with the option -n first. This will only print, what would happen, but not actually change anything. For more information have a look at the man zshcontrib.

Kazak answered 12/7, 2016 at 14:57 Comment(0)
C
2

I'm not too familiar with zsh so I don't know if it supports regular expressions but I don't think you really need them here.

You can match the file using a glob and use a substitution:

for file in a_[0-9].[0-9].tgz; do 
    echo "$file" "${file/a/b}"
done

In the glob pattern, [0-9] matches any number between 0 and 9. ${file/a/b} substitutes the first occurrence of a with b.

Change the echo to mv if you're happy with the result.

Cystic answered 12/7, 2016 at 9:40 Comment(2)
The version number may be like 1.1.1, not limited to 2 numbers. Is it possible to capture all things after a as a group and add this group after b?Hindi
You can match whatever you want in the glob (e.g. a_*.tgz) and use the same substitution "${file/a/b}" to change the letter a to b.Cystic
A
0

Assuming you would like to replace the first character in all files matching a*.tgz with the letter b:

for f in a*.tgz; do
  echo mv "$f" "b${f:1}"
done

Remove the echo when you are certain that this does what you want it to do.

The ${f:1} uses the ${name:offset} parameter expansion. From the zshexpn manual (on OS X):

If offset is non-negative, then if the variable name is a scalar substitute the contents starting offset characters from the first character of the string, [...]

Albuminate answered 12/7, 2016 at 9:55 Comment(0)
Q
0

There is a 'rename' utility that does just that.

On debian install with: sudo apt install rename

then rename "s/^a/b/" a*.tgz

Quincy answered 9/9 at 9:13 Comment(1)
There's more than one so what exactly works depends on where you installed it from.Evzone

© 2022 - 2024 — McMap. All rights reserved.