I have a simple bash script, which forms part of an in house web app that I’ve developed.
It’s purpose is to automate deletion of thumbnails of images when the original image has been deleted by the user.
The script logs some basic status info to a file /var/log/images.log
#!/bin/bash
cd $thumbpath
filecount=0
# Purge extraneous thumbs
find . -type f | while read file
do
if [ ! -f "$imagepath/$file" ]
then
filecount=$[$filecount+1]
rm -f "$file"
fi
done
echo `date`: $filecount extraneous thumbs removed>>/var/log/images.log
Whilst the script correctly deletes thumbs, it doesn’t correctly output the number of thumbs that are being purged, it always shows 0.
For example, having just manually created some orphaned thumbnails, and then running my script, the manually generated orphaned thumbs are deleted, but the log shows:
Thu Jun 9 23:30:12 BST 2011: 0 extraneous thumbs removed
What am I doing wrong that is stopping $filecounter from showing a number other than zero, when files are being deleted.
I’ve created the following bash script to test this, and this works perfectly, outputting 0 then 1:
#!/bin/bash
count=0
echo $count
count=$[$count+1]
echo $count
Edit:
Thanks for the answers, but why does the following work
$ x=3
$ x=$[$x+1]
$ echo $x
4
…and also the second example works, yet it doesn’t work in the first script?
Second Edit:
This works
count=0
echo Initial Value $count
for i in `seq 1 5`
do
count=$[$count+1]
echo $count
done
echo Final Value $count
Initial Value 0
1
2
3
4
5
Final Value 5
as does replacing count=$[$count+1] with count=$((count+1)), but not in my initial script.
You’re using the wrong operator. Try using
$(( ... ))instead, e.g.:EDIT
The other problem you’re bumping into is down to the pipe. Bumped into this one before (with
ksh, but wouldn’t suprise me to find that other shells have the same problem). The pipe is forking another bash process, so when you do the increment, filcount is getting incremented in the subshell that’s been forked after the pipe. This value isn’t passed back to the calling shell as the subshell has it’s own independent environment (environment variables are inherited in called processes, but called process cannot modify the environment of the calling process).As an example, this demonstrates that filecount gets incremented okay:
…so you should see filecount increase in the loop, but the final filecount will be zero because this echo belongs to the main shell, but the forked subshell (which consists purely of the while loop).
One way you can get the value back is like this…
This will only work if you don’t care about any other stdout output in the loop as this throws it all away apart from the last line we output (the final value of
filecount). This works because we’re using stdout and stdin to feed the data back to the parent shell.Depending on your viewpoint this is either a nasty hack or a nifty bit of shell jiggery-pokery. I’ll leave you to decide what you think it is 🙂