Search code examples
bashglob

Replacing multiple preceding numbers from files


Good day,

I have a bunch of files that need to be batch renamed like so:

 01-filename1.txt    > filename1.txt
 02-filename2.txt    > filename2.txt
 32-filename3.txt    > filename3.txt
 322-filename4.txt   > filename4.txt
 31112-filename5.txt > filename5.txt

I run into an example of achieving this using bash ${string#substring} string operation, so this almost works:

for i in `ls`; do mv $i ${i#[0-9]}; done

However, this removes only a single digit and adding regex '+' does not seem to work. Is there a way to strip ALL preceding digits characters?

Thank you!


Solution

  • If you have a single character that always marks the end of the prefix, Pattern Matching makes it very simple.

    for f in *; do
      mv -nv "$f" "${f#*-}";
    done;
    

    Things worth noting:

    In your case, the use of ls does not cause problems, but for a more generalized solution, certain filenames would break it. Additionally, the lack of quotes around parameter expansions would cause issues for files with newlines, spaces or tabs in them.

    The pattern *- matches any string ending with - combined with lazy prefix removal (one # instead of 2), leads to ${f#*-} evaluating to "$f" with the shortest prefix ending in - removed (if one exists).

    Bash's pattern matching is different from and inferior to RegEx, but you can get a little more power by enabling extended pattern matching with shopt -s extglob. Some distributions have this enabled by default.

    Also, I threw the -nv flags in mv to ensure no mishaps when playing around with parameter expansion.


    More Pattern Matching tricks I often use:

    If you want to remove all leading digits and don't always have a single character terminating the prefix, extended pattern matching is helpful: "${f##+([0-9])}"