1

I know head gives you the beginning section of a file. But in this case, I'm trying to go through my source control and find every file that has a shebang line. And I'm failing to get results when I use head. What am I doing wrong?

When I say doesn't work, i mean it returns nothing. But I know it should've returned something.

Works, but slow!

find . | awk '!/((\.jpeg)|(\.jpg)|(\.html)|(\.png))$/ {print $0; }' | xargs grep "#!"

Doesn't Work

find . | awk '!/((\.jpeg)|(\.jpg)|(\.html)|(\.png))$/ {head $0; }' | xargs grep "#!"

Update As @devnull pointed out, and easily verified by googling. I'll list here for reference: Awk Commands

if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
for ( variable in array ) statement
break
continue
{ [ statement ] ...}
variable=expression
print [ expression-list ] [ > expression ]
printf format [ , expression-list ] [ > expression ]
next
exit
  • @manatwork : Yeah, bang on. I don't use awk much but it just occurred to me that print is internal. Throw up an answer if you're sure. – goldilocks Mar 7 '14 at 19:28
  • 5
    head isn't an awk command. – devnull Mar 7 '14 at 19:29
  • Me thinks devnull summed this up. – goldilocks Mar 7 '14 at 19:31
  • @devnull Thanks - I never realized that awk has a specific, and very limited set of commands... shame on me I'll have to add it to my reading list. – user1766760 Mar 7 '14 at 20:50
  • Note that along with the list above, awk also has builtin functions - here is a list for gawk (GNU awk) cs.utah.edu/dept/old/texinfo/gawk/gawk_13.html. Among them is the system function which can be used to run arbitrary programs/commands, although generally there are better solutions than to use this. – Graeme Mar 7 '14 at 21:40
3

Awk is a command which is an interpreter for a programming language that is aimed at simple text processing. Though it can, it's not really meant to be used to call other commands like the head command.

Here, you could have a shell do the work:

find . -type f \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' \
                  -o -name '*.html' \) -exec sh -c '
  for file do
    IFS= read -r line < "$file" &&
       case $line in
         ("#!"*) printf "%s\n" "$file: $line"
       esac
  done' sh {} +

If you wanted to do it with awk, with GNU awk:

find . -type f \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' \
                  -o -name '*.html' \) -exec awk '
    /^#!/ {print FILENAME ": " $0}; {nextfile}' {} +

With other awks:

find . -type f \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' \
                  -o -name '*.html' \) -exec awk '
   BEGIN {
     for (i = 1; i < ARGC; i++)
       if ((getline < ARGV[i]) > 0 && /^#!/)
         print ARGV[i] ": " $0
     exit
   }' {} +
1

Something like grep -R '^#!' . should rapidly give a list of candidates for more detailed analysis.

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.