Help with Bash script - appending sequential numbers
Solution 1:
You can get bash to count for you just by telling it where to start, like this:
$ n=0
$ echo $((++n))
1
$ echo $((++n))
2
$ echo $((++n))
3
You can use printf %03d
to format the result of $((++n))
as 001
002
003
and 010
, 011
etc, for more accurate sorting. Also, there's no point setting -
and _
as variables since they are not going to vary. Your function could be like this:
function rename () {
title="photo"
n=0
for file in *.jpeg; do
printf -v new "$title-$1-$2_%03d.jpeg" "$((++n))"
mv -v -- "$file" "$new"
done
}
Which does:
$ rename birthday 2015
'file_001.jpeg' -> 'photo-birthday-2015_001.jpeg'
'file_002.jpeg' -> 'photo-birthday-2015_002.jpeg'
'file_003.jpeg' -> 'photo-birthday-2015_003.jpeg'
But there is already a useful rename
command in Ubuntu, so you may want to use a different name :)
Solution 2:
Slightly lengthy but usable python alternative. Assuming your naming is consistent with what you have in the example, you could use this function in your ~/.bashrc
. ( Be mindful of the "\" characters. There must be no space after then, only newline )
rename_photos()
{
python -c 'import os,re,sys; \
[ os.rename(f, "photo_"+sys.argv[1]+\
"_"+sys.argv[2]+"_"+re.split("[_.]",f)[-2]+\
"."+re.split("[_.]",f)[-1]) \
for f in os.listdir(".") \
]' "$1" "$2"
}
And call like
rename_photos arg1 arg2
Assuming your naming is consistent, what this does is splits filename into parts at "." and "_" and renames them via os.rename
function
For instance:
$ ls
file_001.jpeg file_002.jpeg file_003.jpeg
$ rename_photos birthday 2016
$ ls
photo_birthday_2016_001.jpeg photo_birthday_2016_002.jpeg photo_birthday_2016_003.jpeg
Script version
Without making it overly complex, here's a small script that does the same function. There's plenty of comment to explain what each part does. The script itself has to be stored in one of the directories that belong in your $PATH
variable, for instance in your ~/bin
folder. Otherwise, it performs exactly the same function ( in addition to printing new filenames )
#!/usr/bin/env python
import os
import re
import sys
# The operates on all files in the current working
# directory, so you would have to cd to your folder
# and run script there.
for item in os.listdir("."):
# We don't wanna rename the script itself ( just in case ) and
# we don't
if os.path.join("./" + item) != __file__ and \
os.path.isfile("./" + item):
title="photo_"
# Old name can be split into parts using _ and . as
# separators, so we only take items between those as one.
# The last item (-1) is extension, and the one
# before extension is number
old_name = re.split("[_.]",item)
new_name = sys.argv[1] + sys.argv[2] + "_" \
+ old_name[-2] + "." + old_name[-1]
print(new_name)
os.rename(item,new_name)
Solution 3:
What I understood, you just want to add sequential numbers to the end. I would personally do this
function rename () {
count=1 #The first photo will get number 1 to the end
title="photo"
h="-"
u="_"
new=$title$h$1$h$2$u
for file in *.jpeg; do
if [ $count -lt 10 ]; then
mv -v "$file" "${new}00$count" #numbers 1-9 will be like 001 002..
elif [ $count -lt 100 ]; then
mv -v "$file" "${new}0$count" #numbers 10-99 like 022 056 etc..
else
mv -v "$file" "$new$count"
fi
count=$[ $count + 1 ] #count variable gets bigger by one
done
}
When the files are renamed, they will get sequential numbers with padding to the end. This could be done differently like indicated in other answers, but I find this pretty easy to understand in case a person doesn't have very good knowledge of bash scripting
Hope this helps!
Solution 4:
You can decide for yourself which is the easier way.
Extracting old numbers
You can get the numbers in your filename with a command like grep:
number=$(egrep -o '[0-9]+' <<< "$file")
The command above saves any sequence of digits (matched by the pattern '[0-9]+') in the variable file (passed in to grep through <<<
) to the variable number.
Generating new numbers
You can try something like the below:
number=0 # initialize number to 0
for file in *.jpeg; do
... # do some stuff here
((number+=1)) # adds 1 to the variable number
done
This generates a number starting from 0 for each of your files.
It may be useful to have numbers formated with a fixed width (i.e. 001 instead of 1) for sorting purposes. In which case you can use printf to get a desired output:
number_formatted="$(printf "%03d" "$number")"
The code above formats "12" as "012" and "321" as "321". The "%03d" specifies the format (0 means prepend 0 to the number, 3 specifies 3 total digits printed, including any 0s).