Effective Script Naming
November 1st, 2017The 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:
#!/bin/sh
# $1 is the path to search
for file in $(find $1)
do
if [ -f $file ]
then
if [ ! -x $file ]
then
head -n 1 $file | egrep "^#!" >/dev/null 2>&1
if [ $? = 0 ]
then
echo $file
fi
fi
fi
done
Naming the script
There is only one name for a script whose entire purpose is to generate a list of weak ineffective shebangs: whung
Is the script still valid if you have blank lines at the beginning? I am thinking probably not but MAYBE.
by Tim A November 2nd, 2017 at 3:42 pmRule #1 of shell programming is to avoid iteration. Here is a more robust and faster version of your script:
[snip]
#! /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}’
[pins]
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’
by James K. Lowden November 21st, 2017 at 11:54 pm@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.
by brent November 22nd, 2017 at 12:36 pm