7

When using grep or egrep to search through the output from a program with the --help parameter it prints the complete output instead of the lines that match.

Example:

ssh-keygen --help | grep "known_hosts"
unknown option -- -
usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
                  [-N new_passphrase] [-C comment] [-f output_keyfile]
       ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
       ssh-keygen -i [-m key_format] [-f input_keyfile]
       ssh-keygen -e [-m key_format] [-f input_keyfile]
       ssh-keygen -y [-f input_keyfile]
       // etc

When searching for a parameter like ssh-keygen --help | grep "-p" grep recognizes this parameter for itself. Escaping the dash (i.e. grep "\-p") does not help.

Example:

ssh-keygen --help | grep "-p"         
grep: invalid option -- 'p'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
unknown option -- -
usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
                  [-N new_passphrase] [-C comment] [-f output_keyfile]
       ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
       ssh-keygen -i [-m key_format] [-f input_keyfile]
       ssh-keygen -e [-m key_format] [-f input_keyfile]
       ssh-keygen -y [-f input_keyfile]
       ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]
       ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
       ssh-keygen -B [-f input_keyfile]

How to solve this? Thanks for any help!

15

The ssh-keygen command doesn’t have a --help option, so it prints the “unknown option” error, silently thinks “RTFM” and outputs the help. It does this not on stdout but on stderr, which is not piped with | but only with |& (which is a bash shorthand for 2>&1 |):

$ ssh-keygen --help |& grep "known_hosts"
       ssh-keygen -F hostname [-f known_hosts_file] [-l]
       ssh-keygen -H [-f known_hosts_file]
       ssh-keygen -R hostname [-f known_hosts_file]

A totally different issue is grep recognizing your search expression as an option because it starts with a hyphen. Fortunately grep is one of the many commands which recognize the “end of options” -- option and takes everything behind it as an argument instead of an option:

$ ssh-keygen --help |& grep -- -p
       ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]

man grep doesn’t even mention it, but here’s this option’s description from the bash manual:

A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments.

grep also provides a second way to deal with patterns beginning with “-”: The -e option takes a pattern as its argument, thus the following is equally possible:

$ ssh-keygen --help |& grep -e -p
       ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]

Further reading

  • great post, but why do you think the grep manual should mention how the shell handles --? It doesn't mention other shell feature,too, like filename expansion, variable expansion, command substitution. There are a lot of things the shell does before te command is executed. I think the grep manual is not the right place for such details. – miracle173 Aug 11 at 5:41
  • @miracle173 bash and some of its builtins understand --, but the shell does nothing with grep -- -p (what would that be?). It’s grep alone that understands this option and its special meaning, therefore its manual page should list it as an option. – dessert Aug 11 at 6:44
  • you are right. I see now that it is restricted to some of the builtins. So it is actually a grep feature. – miracle173 Aug 11 at 7:46
  • @miracle173 By implementing it grep followed POSIX Utility Syntax Guideline 10, so it’s not their idea, but still… – dessert Aug 11 at 7:52
2

You call ssh-keygen with a non-existent option. That is an error, and error output appears on stderr. It does not appear like ssh-keygen has a regular option for outputting its usage: if it had (like GNU programs have by default with --help), that "regular" output would appear on stdout and be accessible to less in the pipe you used.

You can kludge around this using ssh-keygen --help 2>&1 | grep -e "-p" : the 2>&1 redirects stderr to stdout where the pipe can catch it, and -e as an option to grep means "the following is the regexp to use even if it looks like an option".

man ssh-keygen should work better for getting the usage and will pipe into less by default where you can search regular expressions with / , and reading in context is usually the better choice.

2

If what you're looking for is help on the ssh-keygen command try

man ssh-keygen | grep known_hosts

Or, you can do man ssh-keygen from a command line and then press / and type the search term, eg "kno", press Enter, use n to continue to the next instance of the search term (man man for more info about using man). Note the man search only searches down, so use PgUp or Home to return to the start of the manual entry before starting a new search.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.