how to check if the first line of file contain a specific string?
It is easy to check if the first line starts with #include
in (GNU and AT&T) sed:
sed -n '1{/^#include/p};q' file
Or simplified (and POSIX compatible):
sed -n '/^#include/p;q' file
That will have an output only if the file contains #include
in the first line. That only needs to read the first line to make the check, so it will be very fast.
So, a shell loop for all files (with sed) should be like this:
for file in *
do
[ "$(sed -n '/^#include/p;q' "$file")" ] && printf '%s\n' "$file"
done
If there are only files (not directories) in the pwd.
If what you need is to print all lines of the file, a solution similar to the first code posted will work (GNU & AT&T version):
sed -n '1{/^#include/!q};p' file
Or, (BSD compatible POSIXfied version):
sed -ne '1{/^#include/!q;}' -e p file
Or:
sed -n '1{
/^#include/!q
}
p
' file
for file in *; do
[ -f "$file" ] || continue
IFS= read -r line < "$file" || [ -n "$line" ] || continue
case $line in
("#include"*) printf '%s\n' "$file"
esac
done
To print the content of the file instead of its name, replace the printf
command with cat < "$file"
.
If your awk
supports the nextfile
extension, and you don't care about the potential side effects of opening non-regular files:
awk '/^#include/{print substr(FILENAME, 3)}; {nextfile}' ./*
Above, we're adding a ./
prefix which we're stripping afterwards in FILENAME
to avoid problems with file names containing =
characters (or a file called -
).
With zsh
, you can replace ./*
with ./*(-.)
to only pass regular files (or symlinks to regular files like for the [ -f ... ]
approach above) to awk
.
Or to print the file contents instead of name:
awk 'FNR == 1 {found = /^#include/}; found' ./*
(that one is portable).
for file in *
do
[ -f "$file" ] && head -n 1 < "$file" | grep -q '^#include' && cat < "$file"
done
Beware of the fact that, with -q
option enabled, grep
will exit with a zero status even if an error occurred.