Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash script to rename all files in a directory?

Tags:

linux

bash

shell

i have bunch of files that needs to be renamed.

file1.txt needs to be renamed to file1_file1.txt
file2.avi needs to be renamed to file2_file2.avi

as you can see i need the _ folowed by the original file name.

there are lot of these files.

like image 941
gpow Avatar asked Dec 24 '09 00:12

gpow


People also ask

How do I rename all files in a folder?

Click the Select all button. Quick tip: Alternatively, you can also use the Ctrl + A keyboard shortcut to select all files. You can press and hold the Ctrl key and then click each file to rename. Or you can choose the first file, press and hold the Shift key, and then click the last file to select a group.


2 Answers

So far all the answers given either:

  1. Require some non-portable tool
  2. Break horribly with filenames containing spaces or newlines
  3. Is not recursive, i.e. does not descend into sub-directories

These two scripts solve all of those problems.

Bash 2.X/3.X

#!/bin/bash

while IFS= read -r -d $'\0' file; do
    dirname="${file%/*}/"
    basename="${file:${#dirname}}"
    echo mv "$file" "$dirname${basename%.*}_$basename"
done < <(find . -type f -print0)

Bash 4.X

#!/bin/bash

shopt -s globstar
for file in ./**; do 
    if [[ -f "$file" ]]; then
        dirname="${file%/*}/"
        basename="${file:${#dirname}}"
        echo mv "$file" "$dirname${basename%.*}_$basename"
    fi
done

Be sure to remove the echo from whichever script you choose once you are satisfied with it's output and run it again

Edit

Fixed problem in previous version that did not properly handle path names.

like image 58
SiegeX Avatar answered Sep 29 '22 08:09

SiegeX


For your specific case, you want to use mmv as follows:

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2.avi

pax> mmv '*.*' '#1_#1.#2'

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1_file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2_file2.avi

You need to be aware that the wildcard matching is not greedy. That means that the file a.b.txt will be turned into a_a.b.txt, not a.b_a.b.txt.

The mmv program was installed as part of my CygWin but I had to

sudo apt-get install mmv

on my Ubuntu box to get it down. If it's not in you standard distribution, whatever package manager you're using will hopefully have it available.

If, for some reason, you're not permitted to install it, you'll have to use one of the other bash for-loop-type solutions shown in the other answers. I prefer the terseness of mmv myself but you may not have the option.

like image 40
paxdiablo Avatar answered Sep 29 '22 08:09

paxdiablo