简体   繁体   中英

Shell Script Rename

Now I have the rename script like this:

cd /Users/KanZ/Desktop/Project/Test/ 
n=1
for file in *.jpg; do 
    echo $file
    prefix=M
    file_name=M$n.jpg 
    echo $file_name
    n=$(( $n+1 ))
    mv $file $file_name 
done 

The first if I run script, the all of jpg files will be M1.jpg M2.jpg M3.jpg but if I add the new file name A1.jpg to this directory and run script again. All of M1.jpg M2.jpg M3.jpg will be replaced by M4.jpg(before run script, this file named A1.jpg) because the first letter is A. It come before M. This is my problem. I would like to get M1 M2 M3 M4.jpg and every time if there are new files coming, this script will generate the continue name like M5.jpg M6.jpg . How is the code look like? Hope you understand that. Thank u for helping

The other answers given so far don't show you any good practice.

Here's one possibility that assumes that the numbering is continuous (ie, no jump from M4.jpg to M6.jpg ). Without that assumption, the script is safe (it won't overwrite existing files, but will not rename certain files).

#!/bin/bash

shopt -s extglob
shopt -s nullglob

cd /Users/KanZ/Desktop/Project/Test/

# Determine how many files MX.jpg you have (with X a number):
files=( M+([[:digit:]]).jpg )
n=${#files[@]}

for file in !(M+([[:digit:]])).jpg; do
    file_name=M$((++n)).jpg
    mv -vn -- "$file" "$file_name"
done
  • The -n option to mv : no clobber (do not overwrite an already existing file)
  • The -v option to mv : be verbose (so you don't need the echos you had)
  • The -- thing: end of options, only arguments will be found behind (just in case some files will start with a hyphen, that would confuse mv ).

The way i understood your requirement is :

Change all the .jpg file names from what ever name they have to M*.jpg with an incremental number following M.

During multiple runs of the program the count should increase from the highest value of M file that was setup during the last run. For example if the first run of the program created M1, M2, M3 and then you add more files they should start from M4, M5, M6.

But the M1, M2, M3 itself should not be changed.

So a couple of suggestions :

you are setting n=1 at the start of the script. You should use the highest value of Mx.jpg that exists in the file from the previous run.

Second, when you are looking for files and iterating them, exclude all M*.jpg files, so that their names are not replaced.

Do you think this is your requirement. If you have any additional inputs please add a comment. Will send out the script in the next comment.

Test Cases : Existing Files, X.jpg, ASG.jpg, GER.jpg File names after the run : M1.jpg, M2.jpg, M3.jpg

If you just run the script once more after the first run with no additional files: There should not be any change in the file names : M1.jpg, M2.jpg, M3.jpg.

Now Add more files : Z.jpg, A.jpg, B.jpg The file names should be changed as follows :

M1.jpg => M1.jpg, M2.jpg => M2.jpg, M3.jpg => M3.jpg, A.jpg => M4.jpg, B.jpg => M5.jpg, Z.jpg => M6.jpg. So the file names will be M1.jpg, M2.jpg, M3.jpg, M4.jpg, M5.jpg, M6jpg.

This little script will do it.

cd /Users/KanZ/Desktop/Project/Test/ 
n=$(ls -1 | grep '^M' -c)                    # find the number for M files 
ls -1 *.jpg| grep -v '^M' | while read file  # for each of the non-M files
do 
   n=$(($n+1));                       
   new_file=M$n.jpg                          # new name with next available M file name
   mv "$file" "$new_file"                        # rename with new file name
done 

See how it works.

test/rename$ for x in 1 2 3; do echo A$x> A$x.jpg; done;
test/rename$ ls
A1.jpg  A2.jpg  A3.jpg
test/rename$ cat ../rnm.sh 
#!/bin/bash
cd "$1"
n=$(ls -1 | grep '^M' -c)
nfiles=$(ls -1 *.jpg| grep -v '^M');
for file in $nfiles;
do 
   n=$(($n+1));
   new_file=M$n.jpg
   mv $file $new_file
done 
test/rename$ bash ../rnm.sh  ./
test/rename$ ls
M1.jpg  M2.jpg  M3.jpg
test/rename$ for x in 1 2 ; do echo B$x> B$x.jpg; done;
test/rename$ ls
B1.jpg  B2.jpg  M1.jpg  M2.jpg  M3.jpg
test/rename$ bash ../rnm.sh  ./
test/rename$ ls
M1.jpg  M2.jpg  M3.jpg  M4.jpg  M5.jpg
test/rename$ for x in *.jpg; do echo $x; cat $x; done;
M1.jpg
A1
M2.jpg
A2
M3.jpg
A3
M4.jpg
B1
M5.jpg
B2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM