Bash script to rename all files in a directory?

I have a bunch of files that need 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 _ found by the original file name.

there are a lot of these files.

+4
source share
8 answers

So far, all answers have been given either:

  • Require some non-portable tools
  • Break with file names containing spaces or newlines
  • Not recursive, i.e. doesn't go down to subdirectories

These two scenarios solve all these 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 echo from any script that you choose after you are satisfied with its output and run it again

Edit

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

+5
source
 for file in file*.* do [ -f "$file" ] && echo mv "$file" "${file%%.*}_$file" done 

Recursion idea

 recurse() { for file in "$1"/*;do if [ -d "$file" ];then recurse "$file" else # check for relevant files # echo mv "$file" "${file%%.*}_$file" fi done } recurse /path/to/files 
+4
source

In 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 know that wildcards are not greedy. This means that the abtxt file will be converted to a_a.b.txt , not a.b_a.b.txt .

mmv was installed as part of my cygwin, but I had to

 sudo apt-get install mmv 

in my ubuntu field to get it. If this is not a standard distribution, any package manager that you use, we hope that it will be available.

If for some reason you are not allowed to install it, you will have to use one of the other bash for -loop solutions shown in the other answers. I prefer twisting mmv own, but you may not be able to.

+4
source
 find . -type f | while read FN; do BFN=$(basename "$FN") NFN=${BFN%.*}_${BFN} echo "$BFN -> $NFN" mv "$FN" "$NFN" done 
+2
source

I like the PWL cookbook rename script for this. It may not be / bin / sh, but you can do regular expressions like renaming.

The / bin / sh method would have to use sed / cut / awk to change each file name inside the for loop. If the directory is large, you need to rely on xargs.

0
source

Mention should be made of the mmv tool, which was specially created for this.

Described here: http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/mass-rename.html

... along with alternatives.

0
source

I use prename (perl based), which is included in various Linux distributions. It works with regular expressions, so change everything img_x.jpg to IMAGE_x.jpg, you would do

 prename 's/img_/IMAGE_/' img*jpg 

You can use the -n flag to preview changes without any actual changes.

person name record

0
source
 #!/bin/bash # Don't do this like I did: # files=`ls ${1}` for file in *.* do if [ -f $file ]; then newname=${file%%.*}_${file} mv $file $newname fi done 

This will not rename auxiliary directories, only regular files.

-one
source

All Articles