Interview Question, Part 2
OK, let's go ahead to create a 1000 files (img-*.png) and remove some of them for this exercise. In Bash shell, it is very easy to create a 'for' loop from 1 to 1000 to create (touch) 1000 files:
prefix="img-" ext="png" for ((num=1;num<=1000;++num)) do touch $prefix$num.$ext done
There you go, you have 1000 files for free. Suppose we delete img-111.png, img-222.png and img-333.png to represent those missing files that we are suppose to uncover. By using the same construct as given above, we can loop from 1 to 1000 and test the occurrence of the file in each loop. If it does not exist, just simply print out the file name:
prefix="img-" ext="png" for ((num=1;num<=1000;++num)) do fname="$prefix$num.$ext" if [ ! -f "$fname" ] then echo "$fname does not exist" fi done
Mission accomplished, but not for me. Why not challenge yourself by asking these questions, can we do better than that, or can we get away with the loop althogether ? In Bash shell, there is a curly braces syntax that you do not need a 'for' loop. Below shows you how to create 1000 files in a one-liner and how to use the curly braces in a 'for num in' loop. Also, I introduced a 'short-circut' if test in the loop.
$touch img-{1..1000}.png $for fname in img-{1..1000}.png do [ -f "$fname" ] || echo "$fname does not exist" done
Bash shell really give you a lot of flexibility. If you were to use Bourne shell, you will have to explicitly do the counting, like this (code snippet):
num=1 while [ $num -le 1000 ] do ... num=`expr $num + 1` done
Here is the bonus point. You DO NOT need loop in this exercise. As the command line length limit (see /usr/include/limits.h in Solaris) is 1048320 for 32-bit program and 2096640 for 64-bit program, you can take advantage of this to get Bash shell to expand the file name using curly braces.As for the 3 missing files, what you can do is to do a 'ls -l' on 1000 files (use curly braces again) and let the system to report error on the missing files. Since the listing of the 997 files are output to the standard output channel and the 3 missing files are output to the standard error channel, we can just simply re-direct the standard output to /dev/null device. The missing files will be reported automatically.
$touch img-{1..1000}.png $rm -f img-111.png img-222.png img-333.png $ls -1 img-{1.1000}.png > /dev/null img-111.png: No such file or directory img-222.png: No such file or directory img-333.png: No such file or directory
Hope you find this exercise challenging. The whole idea is to always challenge yourself, and do not satisfy with just one solution. Here is the challenge: If you do a 'ls -1' listing of the img-*.png, the order will start with img-1.png, img-10.png, img-100.png, img-1000.png, img-11.png, ... like below. How can we do a listing in numerical order, i.e., img-1.png, img-2.png, img-3.png, ...
$ls -1 img-*.png img-1.png img-10.png img-100.png img-1000.png img-101.png img-102.png img-103.png img-104.png img-105.png img-106.png img-107.png ...
Labels: shell script
0 Comments:
Post a Comment
<< Home