Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am modifying a simple BASH script to remove numbers and hyphens from the start of my MP3 files. The aim is to rename files such as:

  • 11 Song 1.mp3
  • 1-1-Song 2.mp3
  • 11-1 Song 3.mp3


  • Song 1.mp3
  • Song 2.mp3
  • Song 3.mp3

I have this script which works for all the files in the current directory

$ for f in [0-9]*; do mv "$f" "`echo $f | sed 's/^[0-9]*\W*//'`"; done

and have modified it to look for all files inside subfolders:



for f in $(find $dir * -type f) ; do
  mv "$f" "`echo $f | sed 's/^[0-9]*\W*//'`"; 

The problem is that the $f value returns the subfolder and the filename and the mv line looks for files beginning with [0-9], therefore any files within a subfolder are not being renamed.

E.g. The file mp3/1-1 Song 1.mp3 begins mp3/, does not start with a numeric so it's not renamed.

Is there a way I can read the directory and file values into separate variables or is there a better way of doing this?


share|improve this question
+1.nice question – user61928 Oct 16 '12 at 12:37
up vote 4 down vote accepted

find & sed: I would ask you to first remove the pipe and sh at the end, and see whether the mv command is getting generated properly, and then you can run the command as such:

find $dir -type f | sed 's|\(.*/\)[^A-Z]*\([A-Z].*\)|mv \"&\" \"\1\2\"|' | sh
share|improve this answer
Nice solution! Note that this slightly changes the question in that it removes everything before the first upper case character in the filename (instead of just digits and hyphens). If that is desirable, you probably at least want to change both A-Z instances to A-Za-z in case any titles don't contain upper case characters. – glibdud Oct 16 '12 at 13:01
Agree very nice solution - thanks for posting. – Stephen Provis Oct 16 '12 at 16:44

Theres no need for a script, there's a one liner for that.

Try this to see what it does (don't worry, this doesn't rename your files yet, see below):

find root_audio_path -type f -iname '*mp3' -execdir rename --no-act 's/^\.\/[\d\s\-]+/\.\//' '{}' ';'

Remove --no-act if it seems to work. This actually renames the files.

The -execdir option of find makes sure that rename is executed in the files directory, so the files paths always start with ./ - for which we look for in rename.

rename in Ubuntu actually perls rename, so you can use regular expressions there.

share|improve this answer
This seems to work but does not move beyond the parent folder, which is where the problem comes in. – Stephen Provis Oct 16 '12 at 16:40
It works for any number of sub folders as well. The output you see is the one of rename, which is run in every directory. Because it's working directory is always ./, that's all you see. However, the files get renamed in all subdirs. – phoibos Oct 16 '12 at 17:25

The following will get you the path

echo "wwww/www/mp3/1-1 Song 1.mp3" | sed 's#\(.*/\)\(.*\)#\1#g'

The following will get you the file without the path:

echo "wwww/www/mp3/1-1 Song 1.mp3" | sed 's#\(.*/\)##g'
1-1 Song 1.mp3

You will need a variable for the path, old and new filenames. You can get the new filename using your code and build a source and target path using these variables. I'd recommend doing a dry-run where you echo the target appending to a file. Then you can check for d

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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