Effective Script Naming

November 1st, 2017

The Task:

Find all scripts in a directory tree that contain a shebang (the first line of the script starts with a #! comment to tell it how to execute it), but the script is not set as executable, meaning the shebang is ineffective.

The Script:

# $1 is the path to search
for file in $(find $1)
  if [ -f $file ]
    if [ ! -x $file ]
      head -n 1 $file | egrep "^#!" >/dev/null 2>&1
      if [ $? = 0 ]
        echo $file

Naming the script
There is only one name for a script whose entire purpose is to generate a list of weak ineffective shebangs: whung

3 comments to “Effective Script Naming”

  1. Is the script still valid if you have blank lines at the beginning? I am thinking probably not but MAYBE.

  2. Rule #1 of shell programming is to avoid iteration. Here is a more robust and faster version of your script:

    #! /bin/sh
    set -e
    test “$1”

    # find posix scripts
    # get their modes
    # print those whose modes lack an executable bit (“x”)

    find $1 -exec file {} + |
    awk -F: ‘$2 ~ /script/ {print $1}’ |
    xargs stat -f ‘%Sp %SN’ |
    awk ‘$1 !~ /x/ {print}’

    We invoke only 5 processes total, instead of 2 per file, and use only compiled code except for awk’s optimized regular expressions (which need be compiled only once).
    Further, each process executes in parallel.

    For a dozen files, no big difference; for hundreds it will be noticeable.

    stat(1) varies by OS. The above works on a Mac. GNU stat for the same format is

    stat -c ‘%A %n’

  3. @Tim – true, however a shebang has to be on the first line so that’s not just an ineffective one, it’s broken.

    @James – thanks for that and well explained. Yes, I would usually try to keep it in a single pipeline too for all those reasons. With this one, I wanted to keep it more clearly expressed because I know it would have to be understood and maintained in the future by people with varying levels of Unix-Fu.