F does not clearly distinguish between programs and dynamic shared objects, you should normally use either --executable or --shared to identify the primary purpose of a file.  Only one of the --shared and --executable checks can pass for a file.

If you want to know whether an ELF object might a program or a shared library (but could be both), then use --program or --library. Some ELF files will classify as both a program and a library.

If you just want to know whether an ELF file is loadable (as program or library) use --loadable.  Note that files that only contain (separate) debug information (--debug-only) are never --loadable (even though they might contain program headers).  Linux kernel modules are also not --loadable (in the normal sense).

Without any of the --print options, the program exits with status 0 if the requested checks pass for all input files, with 1 if a check fails for any file, and 2 if there is an environmental issue (such as a file read error or a memory allocation error).

When printing file names, the program exits with status 0 even if no file names are printed, and exits with status 2 if there is an environmental issue.

On usage error (e.g. a bad option was given), the program exits with a status code larger than 2.

The --quiet or -q option suppresses some error warning output, but doesn't change the exit status.