8

I have around 180 files with the same structure: 000-aaaaaaaa.txt.

Regular expression for a file name: /^[0-9]{3}\-[a-zA-Z]+$/gi (3 digits + - + letters + .txt).

I would like to cut of the numeral part and - in each file name

For example

  • 000-hello.txt -> hello.txt
  • 001-world.txt -> world.txt
  • 002-ubuntu.txt -> ubuntu.txt
  • 003-linux.txt -> linux.txt
15
+300

Renaming files using mmv:

$ mmv '???-*' '#4'
       ^^^ ^    ^
       123 4    4

You could also match digits with range match:

$ mmv '[0-9][0-9][0-9]-*.txt' '#4.txt'
         ^    ^    ^   ^        ^
         1    2    3   4        4

(recursively rename files):

$ mmv ';???-*' '#1#5'
       ^^^^ ^    ^ ^
       1234 5    1 5
  • ; Expands to any number of directories (same as **/).
  • * Matches any char zero or more times.
  • ? Matches any single character.
  • [] Matches a list or and a range of characters.
  • # References to the nth wildcard char in the from pattern.
| improve this answer | |
  • 2
    This deserves more love - people seem to be resistant to mmv / mcp (perhaps because of the unfamiliar syntax?). Maybe that will change as zsh (which has an equivalent zmv) becomes more popular. – steeldriver Mar 17 at 13:00
13

With Perl-based rename command:

$ rename -n 's/\d{3}-//' [0-9][0-9][0-9]-*.txt
rename(000-hello.txt, hello.txt)
rename(001-world.txt, world.txt)
rename(002-ubuntu.txt, ubuntu.txt)
rename(003-linux.txt, linux.txt)

If the number of files is large enough to make the command exceed the shell's ARG_MAX, then you could use either

printf '%s\0' [0-9][0-9][0-9]-*.txt | xargs -0 rename -n 's/\d{3}-//'

or

find . -maxdepth 1 -name '[0-9][0-9][0-9]-*.txt' -exec rename -n 's/\d{3}-//' {} +

Note that [0-9][0-9][0-9]-*.txt is processed by the shell and needs to be a shell glob expression rather than a regular expression.

Remove the -n once you are happy that it is doing the right thing.

| improve this answer | |
  • will this be subject to 'too many arguments' ? – bac0n Mar 17 at 7:35
  • Not with 180 matching files. If you have thousands of files, you can do ls | xargs rename s/foo/bar/ or find ... -exec rename s/foo/bar/ + – xenoid Mar 17 at 9:17
  • @xenoid I've added some options for that – steeldriver Mar 17 at 11:42
  • @steeldriver That printf thing has been added to my bag of tricks :) – xenoid Mar 17 at 12:02
  • think you can skip xargs, and go printf ... rename --null only – bac0n Mar 17 at 12:08
2

Since I don't see it mentioned here yet, you can use repren. While it isn't installed by default, it does support regular expression-based file renaming. You can do just a single regular expression pattern like so:

repren --rename --from "^[0-9]{3}" --to "" --dry-run .

The above example deletes the first 3 digits in all filenames if they are at the beginning thereof for all files recursively in the current directory. It does a dry run though to show you what it will do without actually doing it - remove the --dry-run bit once you're sure that it will do what you intend.

repren also supports pattern files, allowing you to do multiple replacements in 1 go:

repren --rename --patterns=path/to/patternfile

A pattern file looks like this:

regex_1<tab_character>replacement_1
regex_2<tab_character>replacement_2

...and so on.

Finally, it supports regular expression groups. Consider this pattern file:

# This is a comment
figure ([0-9+])<tab>Figure \1

The \1 syntax inserts the contents of the first (bracketed) group. To do this on the command-line, you'd need to use single quotes I think (correct me if I'm wrong):

repren --rename --from 'figure ([0-9+])' --to 'Figure \1' --dry-run path/to/directory_or_files_here

This is just scratching the surface of what repren is capable of though. It can optionally alter the contents of files too (hence the need for --rename in all the above examples).

Disclaimer: I am not affiliated with repren or it's development in any way, I just find it an invaluable time-saving tool.

| improve this answer | |
  • It's a cool tool. But is there a version that will work on Python 3.x? At the moment this looks like Python 2.x only. Which is bad given Python 2.x just dropped out of support from its authors. – 0xC0000022L Apr 20 at 20:17
  • @0xC0000022L Oh my! I hadn't noticed it was Python because I have it installed from source as a git submodule in my ~/bin directory. Have you tried python3 path/to/repren? – starbeamrainbowlabs Apr 20 at 21:53
  • at first glance it works. But I could not find anything that suggested there is support for Python 3.x. The fact that the main function runs doesn't mean it's been tested deep into all kinds of call paths. And it requires quite a leap of faith to commit to a new tool (however nice it appears to be) when the runtime environment for which it was written is deprecated. Besides, especially for this sort of operations I don't want trial&error as my mode of operation. The setup.py also only mentioned Python 2.7 explicitly. – 0xC0000022L Apr 20 at 22:00
  • @0xC0000022L Hrm. Perhaps someone's forked it? I did write this answer 3 years ago, so I'm unsure of the current situation. I would be interested to know if you find a solution. – starbeamrainbowlabs Apr 20 at 22:38
2

I've done this often in the past using the bulkrename command in ranger, a terminal based file browser. The steps are as follows:

  1. Navigate to the directory that contains the files.
  2. Select all files to be renamed. If you want to select everything within that directory, simply press v.
  3. Use the :bulkrename command, this takes you to a list of all the selected file names in vim or your default editor.
  4. Manipulate the file names in vim to your liking and save!
| improve this answer | |
1

I know the question is tagged with command-line, but if a GUI tool would be useful to you, the Thunar file manager has a great bulk-rename tool. You can install Thunar directly from your package manager. Once it's installed, select the files of interest and then go to "Rename" under the Edit menu.

One big advantage of Thunar is that it gives you a preview of the new names, so you don't have to get your command or regex exactly right the first time. It can also do renaming tasks that are beyond the purview of regexes, like inserting consecutive numbers into file names.

There's more info about Thunar on the Ubuntu package website. Free Software Magazine has a nice overview article about it too, with screenshots.

| improve this answer | |
  • Welcome to AskUbuntu, this is not an exact answer of the question and rename -n does show preview. – Sadaharu Wakisaka Mar 18 at 0:56
0

I generally construct a shell script to rename each file.

I put the output of ls into a file which I edit to make the script. This is trivial in emacs, and probably just as easy in vim.

If I am still unsure of myself, I might have the files in a temporary subdirectory just in case something went wrong. I'd probably use a subdirectory if using mmv, as well.

| improve this answer | |
  • Wait, so you're a suspicious person but you're trusting yourself unconditionally to get the shell script right? And you parse the output of ls? Something doesn't check out here. Bad advice. -1 from me. Sorry. – 0xC0000022L Apr 20 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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