Ubuntu – Replace a word in a directory name and in the filenames in that directory

batch-renamecommand linemvscriptssed

I have a directory structure like this:

Bookname Edition 1
  Bookname Edition 1 type1.pdf
  Bookname Edition 1 type2.pdf
Bookname Edition 2
  Bookname Edition 2 type1.pdf
  Bookname Edition 2 type2.pdf

I want to recursively change the name from Edition to Volume of the directory and the filenames in those directories.

I started off with this and that's fine if I'm in the directory:

for f in *.pdf; do
    a="$(echo $f | sed s/Edition/Volume/)"
    mv "$f" "$a"
done

Then I tried this to change all files under the directories, and that's when I got stuck…

Please can you tell me how to do this or give me a better way of doing this. There are 15000 PDFs in 100 directories.

Best Answer

If your structure only has two levels, you don't need to use recursion.

Don't parse filenames with sed. If you want to use regex and sed style syntax to rename files, use rename. If you're using Ubuntu 17.10, you need to install it

sudo apt install rename

Then you can use pa4080's answer.

With rename, use the -n option for testing.

rename -n 'expression' file(s)

You could also just use the mv command. As a one-line command:

for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done

You can use echo for testing with mv, ie echo mv -v source dest, but it gives inaccurate results here, unless you test and then run the loops separately.

As a script:

#!/bin/bash

# rename directories first
for d in ./*/; do
    mv -v "$d" "${d/Edition/Volume}"
done

# now rename files
for f in ./*/*; do
    mv -v "$f" "${f/Edition/Volume}"
done

mv and rename recognise -- to indicate the end of options. Since all paths begin with ./ in this example, we do not need to use that, but if paths may begin with -, then use -- at the end of options, eg rename -n -- 's/foo/bar/' *, to prevent those paths being interpreted as options.