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
5
  • @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. Commented Mar 7, 2014 at 19:28
  • 5
    head isn't an awk command. Commented Mar 7, 2014 at 19:29
  • Me thinks devnull summed this up. Commented Mar 7, 2014 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. Commented Mar 7, 2014 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. Commented Mar 7, 2014 at 21:40

2 Answers 2

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.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.