0

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!

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Norskyi
  • 155
  • 13
  • 2
    `${i#[0-9]*-}` .. – William Pursell Jul 27 '20 at 19:37
  • But it's not a regex, it's a glob. – William Pursell Jul 27 '20 at 19:38
  • 2
    be careful with constructs like "for i in `ls`" . `for` uses the `$IFS` to split the input items, and that by default includes spaces. I prefer ` find -print0 | xargs -0 ` for this reason. `+` is part of extended regular expressions, but not the original regular expressions historically implemented by `grep`, `sed`, etc. – erik258 Jul 27 '20 at 19:39
  • A very similar question about removing numbers from the begining of a file name was asked two days ago on Unix+Linux: [How do I remove any and all characters before the first period in a file name?](https://unix.stackexchange.com/questions/600246/how-do-i-remove-any-and-all-characters-before-the-first-period-in-a-file-name) – John1024 Jul 27 '20 at 19:47
  • Thanks John, my bad – Norskyi Jul 27 '20 at 19:50

3 Answers3

3

With Perl's standalone rename command:

rename -n 's/.*?-//' *.txt

If output looks okay, remove -n.


See: The Stack Overflow Regular Expressions FAQ

Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • Thanks, I am not sure if something is wrong on my end but this does not do anything, no output. `rename from util-linux 2.35.2` – Norskyi Jul 27 '20 at 19:48
  • 1
    @Norskyi That `rename` is, unfortunately, incompatible with perl's. To get perl's rename, have a look [here](https://unix.stackexchange.com/questions/148379/delete-spaces-hyphens-and-underscores-in-filenames/148380#148380). – John1024 Jul 27 '20 at 21:17
1

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])}"

Jeffrey Cash
  • 1,023
  • 6
  • 12
1
for i in * 
do

name=$( echo "$i" | cut -d "-" -f 2 )
mv "$i" "$name" 2>/dev/null

done