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?



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
  • 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

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.

  • This seems to work but does not move beyond the parent folder, which is where the problem comes in. 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

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.