How to add leading zeros to numbers for file names
Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I basically would like to add zeros before the 1st and 2nd set of numbers but not the 3rd since they already contain 3 digits. I'd like them all to be 3 digits, so two zeros should be added to the 1st set and one zero should be added to the 2nd set. I am not necessarily wanting to add the zeros to the very beginning of the file. Just before the corresponding numbers.
I'd like to get them to look like this:
1) file_004_name.txt
2) file_040_name.txt
Every set contains '_' before and after. Any help would be much appreciated. My limited use of awk and sed isn't helping much.
Thanks,
Shawn
Last edited by rootaccess; 06-15-2012 at 05:41 PM.
In a loop, reading files one at a time--putting the names into the variable "filename":
newname=$(sed -r -e 's/_([0-9])_/_00\1/' -e 's/_([0-9]{2})_/_0\1_/' $filename)
mv $filename $newname
continue loop
I'll test this shortly---unless someone beats me to it.....
UPDATE===this has problems, but I think the SED logic is maybe OK
For starters, it needs to be "echo $filename | sed .....etc"
Last edited by pixellany; 06-15-2012 at 07:07 PM.
Reason: fixed an error
Where from is the part you want to replace with to in files.
Therefore there are two replacements, in the first part all files that have only one digits in the name (file_?_name.txt) get the part file_ replaced with file_0 (for example file_1_name.txt -> file_01_name.txt).
In the second replacement all files with two digits in the name (file_??_name.txt) get the part file_ also replaced with file_0 (for example file_01_name.txt -> file_001_name.txt).
Quite simple once you grasp the concept, it took me some time.
Ok I deliberately made a file called file_1_name.txt and used
Code:
rename file_ file_0 file_?_name.txt
This is the error I get
Code:
Bareword "file_" not allowed while "strict subs" in use at (eval 1) line 1.
Quote:
Originally Posted by TobiSGD
Yes, the syntax is
Code:
rename from tofiles
Where from is the part you want to replace with to in files.
Therefore there are two replacements, in the first part all files that have only one digits in the name (file_?_name.txt) get the part file_ replaced with file_0 (for example file_1_name.txt -> file_01_name.txt).
In the second replacement all files with two digits in the name (file_??_name.txt) get the part file_ also replaced with file_0 (for example file_01_name.txt -> file_001_name.txt).
Quite simple once you grasp the concept, it took me some time.
I believe that formatting with printf can give you leading zeroes, as described here. I use a small function in my scripts for this. A small example:-
Code:
$ # to print an index-number-- an integer padded with preceding zeroes.
$ # $1 = number of digits $2 = number to print
$ function idxnum() { printf "%0${1}d" "$2" ; }
$ numx=40
$ echo file_$(idxnum 3 $numx)_name.txt
file_040_name.txt
EDIT: May it be possible that you run Debian or a derived distro? Seems that they have a different version of the rename command which needs a Perl regular expression: http://tips.webdesign10.com/how-to-b...n-the-terminal
Last edited by TobiSGD; 06-15-2012 at 09:12 PM.
Reason: added info
EDIT: May it be possible that you run Debian or a derived distro? Seems that they have a different version of the rename command which needs a Perl regular expression: http://tips.webdesign10.com/how-to-b...n-the-terminal
when I executed the script, it printed php_040_tut.mp4 so we're getting somewhere but how would I actually mv that file to make the changes instead of just printing it? Would I use xargs mv?
I'm trying to rename a massive amount of files. not just _40_ ...
I would like to rename 20 to 020, 68 to 068, 7 to 007, etc.
What kind of value would I use for the numx variable to call 2 characters? I tried ?? but I guess that won't work. Still trying to figure out this printf stuff. Never thought you could make a function like that. Strange things occur in linux, but that's what's great about it.
Quote:
Originally Posted by dru8274
I believe that formatting with printf can give you leading zeroes, as described here. I use a small function in my scripts for this. A small example:-
Code:
$ # to print an index-number-- an integer padded with preceding zeroes.
$ # $1 = number of digits $2 = number to print
$ function idxnum() { printf "%0${1}d" "$2" ; }
$ numx=40
$ echo file_$(idxnum 3 $numx)_name.txt
file_040_name.txt
What kind of value would I use for the numx variable to call 2 characters?
The first parameter to idxnum defines the number of digits. Whereas the second parm is the index number we want to print. So for example, "40" can be printf here with padded zeroes, using 4 digits, 6 digits, and 9 digits...
but how would I actually mv that file to make the changes instead of just printing it?
Try this please. I've assumed here that the number is always delimited by "_" chars, as you mentioned above. And I've commented out the move command, so you can check that the file renaming is working okay first.
Code:
function idxnum() { printf "%0${1}d" "$2" ; }
for filex in * ; do
numx="${filex#*_}"
numx="${numx%_*}"
echo "$filex ${filex%%_*}_$(idxnum 3 $numx)_${filex##*_}"
# mv -v "$filex" "${filex%%_*}_$(idxnum 3 $numx)_${filex##*_}"
done
Last edited by dru8274; 06-16-2012 at 03:07 AM.
Reason: extra explanation for idxnum
Ok I made 3 test files using php_2_tut.mp4 and it worked for that, but when I tried using it for the real files, they wouldnt work because I have more than just 3 total fields between underscores. And I do see in the script that it is meant for 3 fields but how would I get it to work with any amount of fields, be it 2 fields or 9 between underscores. Let me explain.
The real files vary. They look like this:
beginner_php_tutorial_1_introduction_to_php.mp4
beginner_php_tutorial_30_basic_functions.mp4
beginner_php_tutorial_33_global_variables_and_functions.mp4
beginner_php_tutorial_174_loading_in_file_contents_to_a_div_part_3.mp4
So as you can see, there could be 3 fields after the number 1, and 9 fields after the 174th video.
How would I change the script to correspond with that?
Otherwise it works on files like this:
php_7_tut.mp4
which then became php_007_tut.mp4
I should have been more clear from the very beginning. I have to remember everything is very literal and counts. Sorry for that.
Quote:
Originally Posted by dru8274
The first parameter to idxnum defines the number of digits. Whereas the second parm is the index number we want to print. So for example, "40" can be printf here with padded zeroes, using 4 digits, 6 digits, and 9 digits...
Try this please. I've assumed here that the number is always delimited by "_" chars, as you mentioned above. And I've commented out the move command, so you can check that the file renaming is working okay first.
Code:
function idxnum() { printf "%0${1}d" "$2" ; }
for filex in * ; do
numx="${filex#*_}"
numx="${numx%_*}"
echo "$filex ${filex%%_*}_$(idxnum 3 $numx)_${filex##*_}"
# mv -v "$filex" "${filex%%_*}_$(idxnum 3 $numx)_${filex##*_}"
done
Last edited by rootaccess; 06-16-2012 at 03:17 AM.
So as you can see, there could be 3 fields after the number 1, and 9 fields after the 174th video. How would I change the script to correspond with that?
Okay, so we need to craft ourselves a better rename script. So I've rewritten the rename script, totally different, and using "sed" to extract that number as exactly as poss, and to then rename and move the file.
I've commented it a bit, and added some color. And if the script can't extract a $numx from a filename, then it will print a warning message in red. But the script defaults to just printing out filenames, the original and the modified. And if that looks okay, then you can uncomment the mv command, and then run it again for effect.
Furthermore, the mv command will move the renamed files into a folder ./temp1. Such that after you run the script, the only files left in your current folder will be those files the script couldn't handle. That said, I think it will do the trick. So enuf said...
Code:
function idxnum() { printf "%0${1}d" "$2" ; }
# Color codes
bold="$(tput bold)" # bold text
grn="$(tput setaf 2)" # green text
normal="$(tput sgr0)" # normal text
mkdir temp1 2>/dev/null
for filex in *_[0-9]* ; do
# use sed to extract just the number embedded in the filename
numx="$(echo $filex | sed -n 's/^.*_\([0-9]\+\)_.*$/\1/p')"
# if a valid numx wasn't found then move onto next file. Print a warning in RED!
if [[ ! $numx =~ ^[0-9]+$ ]]
then echo -e "${bold}$(tput setaf 1)FAIL : ${filex}${normal}" && continue
fi
# substitute and replace $numx with an idxnum number. This sed doesn't need quotes.
filev="$(echo $filex | sed s/_${numx}_/_$(idxnum 3 $numx)_/)"
# print to stdout the original and modified filenames.
echo -e "${grn}${filex}${normal}\t\t${bold}${filev}${normal}"
# move filex to new filename filev, and place into ./temp1.
#mv "$filex" "./temp1/$filev"
done
I do have debian and that link is in reference to Debian distros so I dont understand why it isn't working on my end.
Of course is the link for Debian distros. Didi you actually read what was written there? As the link states, Debian (and derivatives) have for some reason a version with a different syntax. The syntax I gave you won't work, you have to use Perl regular expressions for it. Since I am bad with those expressions I can't help you with that, but I would guess that something like
holy hell! That script looks like something from hell but it worked like a charm. I think it would take me a couple months just to try to decipher it!
Anyway, I altered it a bit and just commented out the mkdir temp and when moving I removed the dir only because I need the files to stay in the same directory but I thank you very very much for your help. You're a GENIUS.
Quote:
Originally Posted by dru8274
Okay, so we need to craft ourselves a better rename script. So I've rewritten the rename script, totally different, and using "sed" to extract that number as exactly as poss, and to then rename and move the file.
I've commented it a bit, and added some color. And if the script can't extract a $numx from a filename, then it will print a warning message in red. But the script defaults to just printing out filenames, the original and the modified. And if that looks okay, then you can uncomment the mv command, and then run it again for effect.
Furthermore, the mv command will move the renamed files into a folder ./temp1. Such that after you run the script, the only files left in your current folder will be those files the script couldn't handle. That said, I think it will do the trick. So enuf said...
Code:
function idxnum() { printf "%0${1}d" "$2" ; }
# Color codes
bold="$(tput bold)" # bold text
grn="$(tput setaf 2)" # green text
normal="$(tput sgr0)" # normal text
mkdir temp1 2>/dev/null
for filex in *_[0-9]* ; do
# use sed to extract just the number embedded in the filename
numx="$(echo $filex | sed -n 's/^.*_\([0-9]\+\)_.*$/\1/p')"
# if a valid numx wasn't found then move onto next file. Print a warning in RED!
if [[ ! $numx =~ ^[0-9]+$ ]]
then echo -e "${bold}$(tput setaf 1)FAIL : ${filex}${normal}" && continue
fi
# substitute and replace $numx with an idxnum number. This sed doesn't need quotes.
filev="$(echo $filex | sed s/_${numx}_/_$(idxnum 3 $numx)_/)"
# print to stdout the original and modified filenames.
echo -e "${grn}${filex}${normal}\t\t${bold}${filev}${normal}"
# move filex to new filename filev, and place into ./temp1.
#mv "$filex" "./temp1/$filev"
done
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.