Hi,
I need to find all the executable shell scripts under /home dirctory and its sub directories.
I would like to print the path to the files , which include in the header of the file: #!
(Actually its the first line of the file).
I have tried :
find . -name "*" -type f -exec sh -c '
case "$(head -n 1 "$1")" in
#!*)exit0;;
esac
exit 1
' sh {} \; -print
Quick and dirty longhand for the home directory only as a starter using OSX 10.7.5, default bash terminal:-
#!/bin/bash
> /tmp/listing
> /tmp/exe_scripts.txt
ls -l ~/*.sh > /tmp/listing
while read line
do
if [ "${line:3:1}" = "x" ]
then
echo "$line" >> /tmp/exe_scripts.txt
fi
done < /tmp/listing
cat /tmp/exe_scripts.txt
Results:-
Last login: Sun Apr 19 22:29:11 on ttys000
AMIGA:barrywalker~> cd ~/Desktop/Code/ShellAMIGA:barrywalker~/Desktop/Code/Shell> chmod 755 exescript.sh
AMIGA:barrywalker~/Desktop/Code/Shell> ./exescript.sh
-rwxr-xr-x 1 barrywalker staff 128656 22 Nov 09:36 /Users/barrywalker/03080.sh
-rwxr-xr-x 1 barrywalker staff 128990 6 Dec 22:18 /Users/barrywalker/03083.sh
-rwxr-xr-x 1 barrywalker staff 131697 7 Dec 19:48 /Users/barrywalker/03090.sh
-rwxr-xr-x 1 barrywalker staff 134772 29 Dec 21:05 /Users/barrywalker/03100.sh
-rwxr-xr-x 1 barrywalker staff 135072 30 Jan 20:30 /Users/barrywalker/03120.sh
-rwxr-xr-x 1 barrywalker staff 140746 3 Apr 11:32 /Users/barrywalker/03140.sh
-rwxr-xr-x 1 barrywalker staff 143511 11 Apr 20:37 /Users/barrywalker/AudioScope.sh
AMIGA:barrywalker~/Desktop/Code/Shell> _
This does a recursive look, but does NOT display the directories, OS etc as before:-
#!/bin/bash
> /tmp/listing
> /tmp/exe_scripts.txt
cd ~
ls -lR > /tmp/listing
while read line
do
if [ "${line:3:1}" = "x" ] && [ "${line:$((${#line}-3)):3}" = ".sh" ]
then
echo "$line" >> /tmp/exe_scripts.txt
fi
done < /tmp/listing
cat /tmp/exe_scripts.txt
Results:-
Last login: Sun Apr 19 22:43:41 on ttys000
AMIGA:barrywalker~> cd ~/Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> ./exescript.sh
ls: com.solidstatenetworks.host.savedState: Permission denied
-rwxr-xr-x 1 barrywalker staff 128656 22 Nov 09:36 03080.sh
-rwxr-xr-x 1 barrywalker staff 128990 6 Dec 22:18 03083.sh
-rwxr-xr-x 1 barrywalker staff 131697 7 Dec 19:48 03090.sh
-rwxr-xr-x 1 barrywalker staff 134772 29 Dec 21:05 03100.sh
-rwxr-xr-x 1 barrywalker staff 135072 30 Jan 20:30 03120.sh
-rwxr-xr-x 1 barrywalker staff 140746 3 Apr 11:32 03140.sh
-rwxr-xr-x 1 barrywalker staff 143511 11 Apr 20:37 AudioScope.sh
{SNIP}
-rwxr--r-- 1 barrywalker staff 63938 26 Apr 2014 02250.sh
-rwxr--r-- 1 barrywalker staff 93359 29 Jun 2014 02500.sh
-rwxr--r-- 1 barrywalker staff 106544 29 Jun 2014 02550.sh
-rwxr--r-- 1 barrywalker staff 108239 29 Jun 2014 03000.sh
-rwxr--r--@ 1 barrywalker staff 108463 9 Nov 10:19 03010.sh
-rwxr--r--@ 1 barrywalker staff 110523 9 Nov 10:20 03020.sh
-rwxr-xr-x 1 barrywalker staff 115347 9 Nov 18:46 03040.sh
-rwxr--r-- 1 barrywalker staff 128656 22 Nov 09:36 03080.sh
-rwxr--r-- 1 barrywalker staff 131697 7 Dec 19:48 03090.sh
-rwxr--r-- 1 barrywalker staff 134772 29 Dec 21:05 03100.sh
-rwxr--r-- 1 barrywalker staff 135072 30 Jan 20:30 03120.sh
-rwxr--r--@ 1 barrywalker staff 135072 30 Jan 20:14 AudioScope.sh
-rwxr--r-- 1 barrywalker staff 63938 26 Apr 2014 AudioScope.sh
-rwxr--r-- 1 barrywalker staff 52320 5 Jan 2014 AudioScope_02-01-2014.sh
-rwxr--r-- 1 barrywalker staff 4333 26 Mar 2014 Function_Generator.sh
AMIGA:barrywalker~/Desktop/Code/Shell> _
You're correct in noting that grep and awk aren't both needed; the pattern matching I was doing with grep can just as well be done inside awk .
Note that my earlier suggestion didn't have any problem with spaces (or tabs) in filenames, but it wouldn't work with filenames containing one or more colon characters.
Note also that we haven't been told what OS the submitter is using (and the -0 option in xargs and the -print0 primary in find are not available on all systems (and are extensions not included in the POSIX standards).
The awk nextfile function is also an extension to the POSIX standards, but isn't just available in gawk . The following should be portable to any Linux or UNIX system:
If you want to try this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk . If awk on your system has a nextfile function, the following will run considerably faster:
It can be for someone whose user name is not dwc , does not have a primary group name or supplementary group name staff , and has an executable file named supercalifragilisticexpialidocious somewhere in their search path.
Although not the more efficient, your first attempt was pretty close. The main issue is your case line was ignored interpreted as a comment, starting with a "#".
I also removed '-name "*"' which is useless being always true.
find . -type f -exec sh -c '
case "$(head -n 1 "$1")" in
\#!*) exit 0;;
esac
exit 1
' sh {} \; -print
Answering to your last question, I would start with the "file" command. There is no simple heuristic to sort out shell scripts from other text files so most non shebanged scripts will show up as "ASCII text" with this command:
According to the standards, -name "*" should match every path being evaluated. But, note that the entries . and .. are not evaluated unless they were named as operands on the command line.
No, that won't work. I realised that early on...
Take this as an example, saved as /some/path/HW.
echo "Hello www dot unix dot com."
echo "So executable mode is not needed. <wink>"
Results on OSX 10.7.5, default bash terminal.
Last login: Wed Apr 22 18:35:27 on ttys000
AMIGA:barrywalker~> cd Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> chmod 400 HW
AMIGA:barrywalker~/Desktop/Code/Shell> ./HW
-bash: ./HW: Permission denied
AMIGA:barrywalker~/Desktop/Code/Shell> . ./HW
Hello www dot unix dot com.
So executable mode is not needed. <wink>
AMIGA:barrywalker~/Desktop/Code/Shell> chmod 755 HW
AMIGA:barrywalker~/Desktop/Code/Shell> ./HW
Hello www dot unix dot com.
So executable mode is not needed. <wink>
AMIGA:barrywalker~/Desktop/Code/Shell> _
As Don and achenle have already pointed out __any__ method of detection does not work with reliability.
Also #! or #!/ is a non-starter too, which defeats the object of the OP.
If all the OP wants are the shell scripts that begin with a shebang and/or their drawers then that is indeed possible but I wonder if the OP was aware of the above?
Apoloigies for hijacking this thread, I am clear now...