I would like to count successfully executed files, but I can't get it to go.

This is what I have:

commandline=$(find . -name "*.sh" -exec '{}' \;)
    if [ $commandline -gt 0 ]; then
echo "$successfulScripts out of $allScripts scripts were executed successfully"

I don't mind if content of a script is also shown, but is there any way to despise it?

  • You seem to have negative indents (sometimes). I am struggling to read. – ctrl-alt-delor Mar 27 at 21:31
  • 1
    Despise? What does that mean? – Billy C. Mar 28 at 17:13

You could just let find use the value returned by the script. eg

find . -name "*.sh" -exec '{}' \; -print

will execute the script and then -print will only print the names of those scripts which return 0. The output will be interleaved with the output of the scripts, so maybe you just want to redirect the script output elsewhere. On the other hand, if you want to print a pretty summary at the end, maybe you're looking for something like:

{ find . -name '*.sh' -exec sh -c 'if "$1" >&3; then
    echo success; else echo fail; fi' _ {} \; \
    | awk '/success/{s++} /fail/{e++}
    END {printf "%d successes out of %d\n", s, s + e}
 '; } 3>&1
| improve this answer | |

If you have fewer than 100 scripts:

find . -name "*.sh" | parallel
echo $? jobs failed

If you have more than 100 scripts:

find . -name "*.sh" | parallel --joblog my.log
echo $(cut -f 7 my.log | grep -c '^0$') succeeded
| improve this answer | |
  • I'm not very familiar with parallel, but how does the first solution count the successes? man parallel says it ORs the statuses, not adds them. – Joe Apr 8 at 11:56
  • From man parallel: EXIT STATUS Exit status depends on --halt-on-error if one of these is used: success=X, success=Y%, fail=Y%. 0 All jobs ran without error. If success=X is used: X jobs ran without error. If success=Y% is used: Y% of the jobs ran without error. 1-100 Some of the jobs failed. The exit status gives the number of failed jobs. If Y% is used the exit status is the percentage of jobs that failed. – Ole Tange Apr 8 at 13:02

Your variable commandline would contain the output of the find command and all your scripts. Nothing else.

If you want to run all .sh files and count how many successfully executed, it would be easier to do

shopt -s globstar nullglob dotglob

set -- ./**/*.sh
printf 'Testing %d scripts...\n' "$#"

for script do
    "$script" && success=$(( success + 1 ))

printf '%d out of %d finished successfully\n' "$success" "$#"

The shell options that I set enables the ** glob for matching into subdirectories recursively (globstar), makes non-matching patterns vanish rather than remain unexpanded (nullglob), and makes patterns match hidden names (dotglob).

The code then sets the positional parameters to the list of pathnames of files with a .sh filename suffix. The loop loops over the list and tries to run each one. If a run succeeds, a counter is incremented.

At the end, the counter is outputted.

The special value $# is the length of the list of positional parameters (the number of found scripts).

Note that this code does not care about the output of any of the scripts, only their exit status.

With find, you could output the exit status for each run and then count these:

find . -type f -name '*.sh' -exec sh -c '
    for script do
        "$script" >/dev/null
        printf "%d\n" "$?"
    done' sh {} + |
awk '$1 == 0 { success++ } 
     END     { printf("%d out of %d succeeded\n", success, NR) }'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.