简体   繁体   中英

How to print a specific line of all files in a directory?

I ran into an error saying line 235 of my Makefile has error:

make[4]: Leaving directory `/opt/home/root/native-upstream/native_client/tools/SRC/glibc/wctype'
make  subdir=manual -C manual ..=../ subdir_lib
make[4]: Entering directory `/opt/home/root/native-upstream/native_client/tools/SRC/glibc/manual'
Makefile:235: *** mixed implicit and normal rules.  Stop.
make[4]: Leaving directory `/opt/home/root/native-upstream/native_client/tools/SRC/glibc/manual'
make[3]: *** [manual/subdir_lib] Error 2
make[3]: Leaving directory `/opt/home/root/native-upstream/native_client/tools/SRC/glibc'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/opt/home/root/native-upstream/native_client/tools/BUILD/build-glibc32'
make[1]: *** [BUILD/stamp-glibc32] Error 2
make[1]: Leaving directory `/opt/home/root/native-upstream/native_client/tools'
make: *** [build-with-glibc] Error 2

But I don't know which Makefile has this error, there are tons of Makefiles in my project:

#  find . -name Makefile
./tools/Makefile
./tools/BUILD/.gcc-extra-build-cloog-ppl/doc/Makefile
./tools/BUILD/.gcc-extra-build-cloog-ppl/Makefile
./tools/BUILD/.gcc-extra-build-cloog-ppl/test/Makefile
./tools/BUILD/.gcc-extra-build-gmp/printf/Makefile
./tools/BUILD/.gcc-extra-build-gmp/doc/Makefile
./tools/BUILD/.gcc-extra-build-gmp/tests/Makefile
./tools/BUILD/.gcc-extra-build-gmp/tests/devel/Makefile
...

So I would like to print line 235 of each Makefile to find out who is the culprit, something like:

./tools/Makefile: 235: $(objpfx)c++-types-check.out: $(check-data) scripts/check-c++-types.sh
./tools/BUILD/.gcc-extra-build-cloog-ppl/doc/Makefile: 235: ifneq (,$(check-data))
./tools/BUILD/.gcc-extra-build-cloog-ppl/Makefile: 235: $(objpfx)c++-types-check.out:
./tools/BUILD/.gcc-extra-build-cloog-ppl/test/Makefile: 235: endif
./tools/BUILD/.gcc-extra-build-gmp/printf/Makefile: 235:
./tools/BUILD/.gcc-extra-build-gmp/doc/Makefile: 235:
./tools/BUILD/.gcc-extra-build-gmp/tests/Makefile: 235: #   Master Makefile for the GNU C library
./tools/BUILD/.gcc-extra-build-gmp/tests/devel/Makefile: 235:

Is there any way to do this?

It looks like the problem is in /opt/home/root/native-upstream/native_client/tools/SRC/glibc/manual/Makefile , given that the line immediately before the error says it's entering that directory:

make[4]: Entering directory `/opt/home/root/native-upstream/native_client/tools/SRC/glibc/manual'
Makefile:235: *** mixed implicit and normal rules.  Stop.

That said, there are a few ways you could find line 235 of each Makefile. People have already pointed out awk and sed solutions. If you want the filename as well, a quick and easy solution is to use grep :

find . -name Makefile -print0 | xargs -0 grep -nH $ | grep :235:

The find command finds all files named Makefile, printing them out null-delimited (so that you don't have problems if there are files with spaces in their names). xargs passes those filenames to grep . grep -nH prints the filename and line number for every matching line; the $ as the pattern ensures that every line matches (it matches the end of each line). Then you grep within that for the line number you're looking for.

It's not perfect; you might find a few lines that happen to contain ":235:" in them, but it should be fine for a quick one-off (if you really care, you could use `grep '^[^:]*:235:' to ensure that you only match the line number).

I suppose the most straightforward way would be

sed -n '235p' *

That would print line 235 of all the files in the current directory. If you want to recurse through directories, or exclude certain files, you'll have to use a more explicit glob or find with -exec .

So in the end, what you probably want is this:

find . -type f -name Makefile -print -exec sed -n '235p' {} \;

Here's a solution with find and awk

find -type f -name "Makefile" -exec awk 'FNR==235 {print FILENAME; print}' {} +

This prints:

  • Name of Makefile
  • Line 235 of that Makefile

Explanation:

  • find -type f -name "Makefile" - Recursively find all files from current working directory that are named Makefile
  • -exec awk 'FNR==235 {print FILENAME; print}' {} + -exec awk 'FNR==235 {print FILENAME; print}' {} + - For each such file found, use awk to print its name, and then its content at line 235.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM