0

I've been reading about Bulk rename, change prefix and would try with my own files.

In this case, I would like to remove Old and replace it with New

Test Files

01. Old Name.txt
02. Old Name.txt
03. Old Name.txt

Attempt 1

for f in *.txt
do
    mv "$f" "New${f#Old}"
done

Output 1

New01. Old Name.txt
New02. Old Name.txt
New03. Old Name.txt

Attempt 2

for i in *.txt
do
    mv ${i} ${i/#Old/New}
done

Output 2 (no changes)

user@linux:~$ for i in *.txt
> do
> mv ${i} ${i/#Old/New}
> done
mv: target 'Name.txt' is not a directory
mv: target 'Name.txt' is not a directory
mv: target 'Name.txt' is not a directory
user@linux:~$ 

What's wrong with my solution?

Desired Output

01. New Name.txt
02. New Name.txt
03. New Name.txt
  • 1
    Just use the perl rename command. It's just as "built-in" as the mv command. i.e. neither of them are "built-in" to bash, they're both external commands run from the shell. And, like GNU coreutils (which contains mv), it's available pre-packaged for most, if not all, linux distributions. rename 's/Old/New/' *.txt – cas Oct 05 '19 at 06:10
  • 1
    BTW, your 2nd attempt fails because you didn't double-quote the arguments. Try mv "${i}" "${i/Old/New}". See Why does my shell script choke on whitespace or other special characters? – cas Oct 05 '19 at 06:13
  • Thanks @cas. If I quote it, I'll get this error mv: '01. Old Name.txt' and '01. Old Name.txt' are the same file –  Oct 05 '19 at 06:21
  • rename is not built-in .. need to install it. I've problem with a few servers whereby we cannot simply install anything new to it

    `Command 'rename' not found, but can be installed with:

    sudo apt install rename `

    –  Oct 05 '19 at 06:21
  • as i pointed out, mv is not "built-in" either. – cas Oct 05 '19 at 06:24
  • also, did you try mv "${i}" "${i/Old/New}" as i suggested, or with a # like mv "${i}" "${i/#Old/New}" as in your attempt 2? The former will work. The latter won't. – cas Oct 05 '19 at 06:27
  • I did, see my 2nd comment above. This will produce error mv: '01. Old Name.txt' and '01. Old Name.txt' are the same file –  Oct 05 '19 at 06:34
  • no, it doesn't. see my answer. – cas Oct 05 '19 at 06:34

1 Answers1

1
  1. Quote your variables. Also, use ${i/Old/New} without the hash character (#) before Old. The # forces the match to start at the beginning of the filename, but none of the files begin with Old, they all start with 0.

    $ touch "01. Old Name.txt" "02. Old Name.txt" "03. Old Name.txt"
    $ for i in *.txt ; do mv -v "$i" "${i/Old/New}" ; done
    renamed '01. Old Name.txt' -> '01. New Name.txt'
    renamed '02. Old Name.txt' -> '02. New Name.txt'
    renamed '03. Old Name.txt' -> '03. New Name.txt'
    
  2. Install and use the perl rename utility (e.g. sudo apt-get install rename on debian and derivatives). It's far better than DIY bulk renaming.

icarus
  • 17,920
cas
  • 78,579
  • Got it, there was extra # on my script .. thanks it works! –  Oct 05 '19 at 07:29
  • 1
    Also, use mv -i or -n on an automated/bulk move/rename operation like this, to avoid the risk of data loss in case there are any name conflicts (or mistakes in the renaming). – Gordon Davisson Oct 05 '19 at 07:50
  • 1
    and that's yet another reason to use the perl rename command. It won't overwrite existing files unless you force it to with -f, --force. – cas Oct 05 '19 at 09:53