Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

shell script - pls help

Status
Not open for further replies.

santanudas

Technical User
Mar 18, 2002
121
GB
hi guys,

Need to write a bash script which will increment the numbers by 1 but the number should be with leading zero, i.e. 01, 02, 03 etc.

So, if I do

#!/bin/bash
s=`seq -w 5 12`
for i in $s
do
echo $[i+1]
done

not returning the desired result. I tried replacing “$[i+1]” with “$[s+1]” and that doesn't work too. What wrong am I doing? Any guys out here to help?

Thanks in advance.
 
You're going to run into a problem, since bash interprets numbers with a leading zeor as octal, so when you try to do 08, you'll get an error because it's not a valid number. Other than that, you could use 'printf "%02d\n" $[i+1]' to get your formatting. You'll have to strip off the leading zeros before you do the addition.
 
thedaver,
`seq 5 12` was just an example. Actually what I’m doing is:

r=`ls /some-dir/ | wc -l`
s=`seq -w 1 ${r}`

so, I know the number. Right now it’s 57; no wonder if it gets 200 tomorrow or the day after. And as dfdf says, I figured out still I’m in trouble even if I do like 01, 02, 03……


ericbrunson,
thanks for the quick fix; it’s probably gonna help me (didn’t try yet) in the beginning but I guess still I’ll be in trouble alter on.
Eventually I need to create the files with a name like DSF00$[i+1].xml and need to call DSF00$[i-1].xml as well time to time. The name of the file should be like DSF0001.xml, DSF0002.xml, DSF0015 .xml and so on. So I think 'printf "%02d\n" $[i+1]' gonna be fine for the files from 1 to 9 putting DSF000 as the fixed part. But from the 10 to rest of them, the filename gonna be like thisDSF000012.xml, I assume, if I use 'printf "%02d\n" $[i+1]' format. Am I wrong in thinking that? If I’m not, then any other thoughts??
 
Oopps....the line should be "so, I never know the number....
 
something strange is going on here, which I yet to understand.
Chk this out. Below is the test script:

#!/bin/bash
s=`seq -w 6 9`
for i in $s;
do
m=`printf "%02d\n" $[i+1]`
echo "$i => DSF00${m}"
done

now, running this script, I get:

$ bash test.sh
6 => DSF0007
7 => DSF0008
8 => DSF0009
9 => DSF0010

exactly in oredr. Now things are changed if I replace the line s=`seq -w 6 9` by s=`seq -w 6 10`

$ bash test.sh
06 => DSF0007
07 => DSF0008
test.sh: line 1: 08: value too great for base (error token is "08")
08 => DSF00
test.sh: line 1: 09: value too great for base (error token is "09")
09 => DSF00
10 => DSF0011

What's wrong with 10? Does it actually explaining that 08 problem?? How??
 
Okay, maybe I know what it is. For s=`seq -w 6 9`, since the number sequence is not being formed with the leading zero, hence it's fine. As s=`seq -w 6 9` forces to add 0 in front of the number (1 to 9), it's giving problem. Sorry, I overlooked it. But it looks like 09 is also not okay with that.
 
Hint: 08 and 09 are not valid octal numbers.

Alternatively, you could use a different kind for loop in bash, like this...
Code:
for (( i=1 ; i<=10 ; ++i ))
do
   m=$(printf "%04d\n" $i)
   echo "$i => DSF00${m}"
done
Which gives...
Code:
1 => DSF000001
2 => DSF000002
3 => DSF000003
4 => DSF000004
5 => DSF000005
6 => DSF000006
7 => DSF000007
8 => DSF000008
9 => DSF000009
10 => DSF000010
 
ygor, thanks for the code but still not good enough to do my job. My problem is with the increment. So, if I do like this:

for (( i=1 ; i<=20 ; ++i ))
do
m=$(printf "%04d\n" $i)
echo "$i => DSF000$[m+1]"
done

the result is:

1 => DSF0002
2 => DSF0003
3 => DSF0004
4 => DSF0005
5 => DSF0006
6 => DSF0007
7 => DSF0008
./for-i.sh: line 7: 0008: value too great for base (error token is "0008")


Here is a different approach, one my friends and I figured out.

export last=12
export nr=6
while [ $nr -le $last ]; do

export MYFARMNR=`printf %3s $nr | tr " " "0"`
let next=$nr+1
export NEXTNR=`printf %3s $next | tr " " "0"`
echo "$MYFARMNR => DSF0$NEXTNR"
let nr=$nr+1
done

And the result here is:

006 => DSF0007
007 => DSF0008
008 => DSF0009
009 => DSF0010
010 => DSF0011
011 => DSF0012
012 => DSF0013

Exactly the one I was after. %3s substrings with exactly 3 characters. If there are less than 3 characters, the missing ones are blanks, that are translated into 0 by tr.

That I got so far.
 
what was so close is so working now:
Code:
#!/bin/bash
for (( i=1 ; i<=20 ; ++i ))
do
   m=`printf "%04d\n" $i`
   echo "$i => DSF000$m"

done

[root@missioncontrol ~]# ./counter
1 => DSF0000001
2 => DSF0000002
3 => DSF0000003
4 => DSF0000004
5 => DSF0000005
6 => DSF0000006
7 => DSF0000007
8 => DSF0000008
9 => DSF0000009
10 => DSF0000010
11 => DSF0000011
12 => DSF0000012
13 => DSF0000013
14 => DSF0000014
15 => DSF0000015
16 => DSF0000016
17 => DSF0000017
18 => DSF0000018
19 => DSF0000019
20 => DSF0000020



______________________________________________________________________
There's no present like the time, they say. - Henry's Cat.
 
I would edit and say maybe just
Code:
#!/bin/bash
for (( i=1 ; i<=20 ; ++i ))
do
   m=`printf "DSF%06d\n" $i`
   echo "$i => $m"

done

make the printf do more of the work, so $m is completed in one step instead of 2?

______________________________________________________________________
There's no present like the time, they say. - Henry's Cat.
 
Posters need to stop focusing on the loop and start focusing on the increment.

input: 009
output: 010

Do that and the rest is already solved...

The only solutions I've come up with in bash require running a subcommand and are, therefore, incredibly inefficient. You may consider changing to a language more suited to string manipulation.

Here's a solution in awk, which isn't the lightest weight, but not too bad:
Code:
echo 009 | awk '{ printf( "%03s\n", $1 + 1 ) }'
Suitable for using in a shell script.

Here's your solution in python:
Code:
>>> x="009"
>>> print "%03d" % ( int( x ) + 1 )
010
Python is now standard on most Linux distributions, personally I love the language, you may consider writing the entire script in it if you have to convert.
 
ericbrunson was absolutely right; I need some lights on the increment, looping is already done.

I came up with another funny solution:
for i in `seq -w 6 10`; do { echo $i 0`echo $i + 1 | bc ` 0`echo $i - 1 | bc -l `;}; done | sed 's/[0123456789]\([0123456789][0123456789]\)/\1/g'

But in the end, I too, feel that Perl or Python or probably PHP (as it gonna be web based eventually) would be the best to do that. The problem is to rewrite the program in Python, I've to learn it very quickly. lol

Thanks to all.
 
I did focus on the increment, it works perfectly.

Where didn't it perform as required, or did I miss something extremely basic like learning to read ?



______________________________________________________________________
There's no present like the time, they say. - Henry's Cat.
 
I note on 3rd reading that you may want to find $i-1, would that be the number of files in the dir -1? or from the middle of the files -1?

whatever,

FILES=(`ls *.ext`) # *.ext not req'd but will filter for a type
echo ${#FILES[@]} # will show the (int)count of files which meet the criteria.

for here you can step thru the files calling each as you need it:

${FILES[$i]} references the appropriate file.





______________________________________________________________________
There's no present like the time, they say. - Henry's Cat.
 
Want to buy an edit button.

*note: as an array, it begins at 0. ${FILES[0]}

______________________________________________________________________
There's no present like the time, they say. - Henry's Cat.
 
Unless I'm missing something, the "increment" is not complex at all...
Code:
for (( i=1 ; i<=10 ; ++i ))
do
   ((j=i+1))
   m=$(printf "%04d\n" $j)
   echo "$i => DSF00${m}"
done
...which gives...
Code:
1 => DSF000002
2 => DSF000003
3 => DSF000004
4 => DSF000005
5 => DSF000006
6 => DSF000007
7 => DSF000008
8 => DSF000009
9 => DSF000010
10 => DSF000011
 
Up till today, I have no idea what on God's green earth are you trying to do. Maybe if you explain your project in more detail can we give you more meaningful information.


--== Anything can go wrong. It's just a matter of how far wrong it will go till people think its right. ==--
 
So, zeland, do you think everybody else was replying without knowing what they are talking about? In my first and 2nd post, I tried to describe what sort of thing I'm after and I hope people, those who have replied, understood that. If you get a solution and take a moduler approch, then it could be used any where, where ever it fits regardless the project.

Ygor's new fix is pretty much working now and the one too I came up with. So, I'm pleased to say the my problem is solved now. Thanks to all those who helped me to understand and the fix the problem. You guys are really helpful.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top