find . -type f -executable -exec sh -c "[[ \"\$(head -c 4 -- \"\${1}\")\" == \$'\\x7FELF' ]]" -- \{\} \; -print
has the advantage that it doesn't "escape find
". Instead of the final -print
(or after it) you can add other filters or commands while still acting within the find
.
The part
-exec sh -c "[[ \"\$(head -c 4 -- \"\${1}\")\" == \$'\\x7FELF' ]]" -- \{\} \;
acts as a filter in the find
, discarding files that do not start with the ELF file marker.
I'm not sure if the
-type f -executable
part is truly needed, especially both conditions at once. But I guess in large trees it might be faster to discard the paths first based on the elementary properties, before trying to read them.
In my particular use case (that lead me here) I was trying to capture some basing ELF data of all executables generated by a build. However, the tree contained also other (non-ELF) executable files, like for example shell scripts. That caused readelf
to fail and break the find
. Adding the filter to discard non-ELF files first resolved the problem. For completeness, my full command was:
find . -type f -executable -exec sh -c "[[ \"\$(head -c 4 -- \"\${1}\")\" == \$'\\x7FELF' ]]" -- \{\} \; -print -exec readelf -d -- \{\} \;
binfmt_misc
you can run arbitrary files like classes, exes etc. en.wikipedia.org/wiki/Binfmt_miscbinfmt_misc
. Binary formats are as flexible as filesystems on Linux. By all means, find ELFs, but (a) you're not finding all executable files, (b) the ELFs you find aren't necessarily executable in practice. For instance, a SPARC64 ELF won't run on an x86.