8

I am following a series of tutorials to learn Bash shell script. One of the exercises is to loop through files in the current directory and search for a pattern in those files. If the pattern is found then the script should sum the file size of those files.

#!/bin/sh
patern=echo
totalSize=0

for file in * 
do
    [ ! -f $file ] && continue  

    if grep $patern $file > /dev/null
    then    
        echo "pattern matched in $file" 
        echo "file size is `stat -c%s $file`"
        fileSize=`stat -c%s $file`

        totalSize=`expr $totalSize + $fileSize`
        echo "size so far is $totalSize bytes"
        echo                                                    
    fi
done

I have one other folder in the directory from which I am running the script. The folder is called "somedir". It is empty. I have took a snippet of output text pasted below. The middle 3 lines show when the loop iterates over the directory "somedir" which it prints as "sum_files"- my script name along with a file size.

I don't understand this behaviour. How can an empty directory have a file size?
But my main concern is as to why the continue keyword is not stopping the loop iteration. The output is showing that the script is running the below if statement containing the grep command even though it should stop if a directory is found.

I have verified that the test command[ ! -f $file ] does in fact return 0 when the loop gets to the directory and thus the && continue should be invoked. So why does the program continue with the rest of the loop code and try to grep the directory rather than just skipping the loop iteration at continue as expected? I know this is rather trivial but would like to know what's going on here.

Output text

pattern matched in retirement
file size is 396
size so far is 6385 bytes

pattern matched in sum_files
file size is 398
size so far is 6783 bytes

pattern matched in tp0
file size is 164
size so far is 6947 bytes

Drok
  • 113
  • 1
  • 7
  • Use shellcheck.net to identify a few other errors in your script. – chepner Sep 20 '15 at 14:11
  • Your question doesn't make sense… this doesn't make sense: _The middle 3 lines show when the loop iterates over the directory "somedir" which it prints as "sum_files"_. Try `set -x` to see what happens. – gniourf_gniourf Sep 20 '15 at 14:29
  • @gniourf_gniourf "pattern matched in sum_files---file size is 398---size so far is 6783 bytes". From the terminal output. Each file outputs 3 lines of text showing the file name if a pattern match was found, its file size and the summed total. Here I am displaying the anomaly where the for loop iteration runs over the folder "somedir", which shouldn't happen. Where should I "set -x" in the code? – Drok Sep 20 '15 at 14:33
  • The loop runs over the file _sum_file_. Put `set -x` just after `#!/bin/sh`. – gniourf_gniourf Sep 20 '15 at 14:41
  • Actually @gniourf_gniourf you are right because I am running the script in my bin file where the script file is so of course this doesn't make any sense because the script is finding itself. LOL. – Drok Sep 20 '15 at 14:50
  • Yep. This question should be closed `:)`. – gniourf_gniourf Sep 20 '15 at 15:00
  • Possible duplicate of [Check if file exists and continue else exit in Bash](https://stackoverflow.com/questions/9146136/check-if-file-exists-and-continue-else-exit-in-bash) – jww Mar 31 '18 at 22:06

2 Answers2

10

continue continues the loop, as if it reached its bottom.

To break out of the loop use break.

More on bash scripting here: http://tldp.org/LDP/abs/html/index.html

alk
  • 69,737
  • 10
  • 105
  • 255
  • I understand from the tutorial I am following and http://tldp.org/LDP/abs/html/loopcontrol.html#EX28 from this link that: Continue will stop the current iteration of the loop, where break will stop the whole for loop as if it reached the end of all files. When I subsitute break for continue the script will stop searching any other files once it finds a directory which is not the behaviour I want – Drok Sep 20 '15 at 14:21
  • FYI, a return code of 0 means success, so the rhs of the `&&` _will_ be executed. Shell is not C. – gniourf_gniourf Sep 20 '15 at 14:42
  • @gniourf_gniourf: This is not about return codes but about the boolean expression to which `[ ! -f $file ]` evaluates, that is `true` of `false`. (http://tldp.org/LDP/abs/html/fto.html) – alk Sep 20 '15 at 14:47
  • return code of 0 means true (or, rather, success). Try it: `true; echo $?` and `false; echo $?`. Once again, shell is not C. – gniourf_gniourf Sep 20 '15 at 14:58
  • Yes this is what I understand. The output is as expected now. I verified the `[ ! -f $file ]` by running echo $? after it and got 0 when the directory iterated in the loop. Sorry for the confusion. I could not see the wood for the trees! – Drok Sep 20 '15 at 15:02
  • Guys, my mistake was is wrote the `!` but missed to parse it in my brain. – alk Sep 20 '15 at 15:04
  • Recommending the ABS is dubious advice, there are many other tutorials which are more accurate and more helpful. The ABS got really lucky to have gained the visibility that being part of TLDP used to bring, but it got there on questionable merits. – tripleee Apr 04 '18 at 04:38
  • @tripleee: "*which are more accurate and more helpful*": Your proposal were appreciated. Happy to adjust my answer. – alk Apr 04 '18 at 17:59
  • http://wiki.bash-hackers.org/scripting/tutoriallist has ratings for a number of tutorials. The top-rated one at the competing wiki is by @lhunath and IIRC designed to replace the ABS. See also sentiments e.g. at https://unix.stackexchange.com/questions/242111/using-reserved-codes-for-exit-status-of-shell-scripts though I could not quickly find a canonical "ABS Considered Harmful". It's mainly unclear and quirky and sometimes tiresomely verbose more than flat-out wrong. – tripleee Apr 04 '18 at 18:24
2

As to your question about how a empty directory can have a size: directories technically just files themselves, and in order to establish themselves as directories they need some data to let the file system know that.

enter image description here

Gombat
  • 1,994
  • 16
  • 21
  • You shouldn't rely on this though. Some filesystems return 0. Ceph-fuse, for example, reports the total size of all containing files as the folder's size. – Joachim Wagner May 18 '22 at 13:37