12

I find myself doing <command> --help | grep <feature> very very often everyday. I was wondering if it was possible to make something like ^^ that expands to "--help | grep" and then I do this:

ls ^^ size

That would execute the following:

ls --help | grep size
17

You can use a bash function for that:

Put the following in your ~/.bashrc:

qh() {
    type -all "$1" ; { man "$1" || "$1" --help ;} | egrep -i -- "$2"
}

When you save your bashrc do source ~/.bashrc then you can do:

$ qh ls size
      --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                               '--block-size=M' prints sizes in units of
  -h, --human-readable       with -l and/or -s, print human readable sizes
  -s, --size                 print the allocated size of each file, in blocks
  -S                         sort by file size, largest first
      --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
  • 1
    you should quote $1 and $2. I'd change this into : qh () { type -all "$1" ; { "$1" --help || man "$1" ;} | egrep -i -- "$2" ;} # hence you could: qh ls size , qh ls "something|another" etc. the (optionnal) type -all "$1" also add the info about $1: it says if you will be launching an alias, a function, a command, etc.And it gives out info from man "$1" if the command $1 didn't have the option "--help" (this happens sometimes) – Olivier Dulac Jan 11 '18 at 12:36
  • 1
    @OlivierDulac Can you please explain a bit more about type -all "$1"? In what case will it be necessity? – tgwtdt Jan 12 '18 at 15:03
  • My version of type (kubuntu 16.04) knows about -a, but doesn't say anything about -l or -all, but the function does work. – Joe Jan 13 '18 at 7:20
15

With zsh, you'd use a global alias:

$ alias -g '^^=--help|grep --color -i'
$ ls ^^ size
     --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
                              1,048,576 bytes; see SIZE format below
 -h, --human-readable       with -l and/or -s, print human readable sizes
 -s, --size                 print the allocated size of each file, in blocks
 -S                         sort by file size, largest first
     --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
 -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
The SIZE argument is an integer and optional unit (example: 10K is 10*1024)

With bash, you may be able to use history expansion which is one that happens early enough in the shell syntax parsing that it can work at substituting a pipe:

  1. Prime the history with a the text you want to substitute and a special character you're unlikely to use otherwise (like £ here that happens to be on my keyboard):

     $ --help $(: £)|grep
     bash: --help: command not found
     Usage: grep [OPTION]... PATTERN [FILE]...
     Try 'grep --help' for more information.
    
  2. Then using history expansion to retrieve that:

    $ ls !?£? size
    ls --help $(: £)|grep size
         --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
     -h, --human-readable   with -l and/or -s, print human readable sizes
     -s, --size             print the allocated size of each file, in blocks
     -S                     sort by file size, largest first
         --sort=WORD        sort by WORD instead of name: none (-U), size (-S),
     -T, --tabsize=COLS     assume tab stops at each COLS instead of 8
    

Or you could have readline expand --help|grep upon some key or key sequence press. For that to apply to bash only (and not other applications like gdb using readline), you can use the bind bash builtin command which is bash's API to configuring readline, for instance in your ~/.bashrc:

bind '"^^": "--help|grep "'

Or add to your ~/.inputrc (readline's configuration file):

$if Bash
"^^": "--help|grep "
$endif

(there are other shells like rc or es that use readline and where doing that binding could make sense but AFAICT, they do not set the rl_readline_name variable before invoking readline so you won't be able to add some $if statements for them (they would show as other like all applications that use readline without telling it their application name)).

Note that you need to enter the second ^ within half a second (by default) after the first one for the substitution to occur.

  • Can you explain the readline solution a little bit more?! where should I add that binding? on what applications will that binding expand? – yukashima huksay Jan 11 '18 at 8:33
  • @yukashimahuksay, see edit – Stéphane Chazelas Jan 11 '18 at 9:14
8

You could use readline bindings:

add a line like

"^^": "--help | grep "

to your ~/.inputrc

Then press ^X ^R in your term, and the binding will be activated.

Keying ls ^^ will now result in ls --help | grep.

  • I answered before i saw, that Stephane had added the readline solution. I deleted my answer, but then undeletes, when I saw the comment asking about details for the readline solution – Alex Stragies Jan 11 '18 at 8:35
  • 2
    I've now added some more on that in my answer. – Stéphane Chazelas Jan 11 '18 at 9:15
  • 1
    Targeted answers like yours, and comprehensive ones like Stéphane's, both have their place. Have an upvote! – bishop Jan 11 '18 at 14:51
5

Using less to view the help message

You may find it useful to see the surrounding context of the lines that match your search query.

hh () { "${1}" --help | less -p "${2}" ; }

The syntax to call this bash function is similar to the function qh in @tgwtdt's answer, with the first argument being the command to examine, and the second argument being the search term. For example:

hh ls size
hh ls "symbolic link"

This opens the full help message in less, highlights every instance of the search term, and scrolls to the first instance of the search term. You can then press n to scroll forward to the next line containing the search term, n again for the next, and so on. To scroll back to a previous instance, press N. Use the Home, End,Page Up, Page Down, Up Arrow, and Down Arrow keys for general navigation. Press q or Q to exit less and return to the command line.

3

I liked the solution by @tgwtdt, so I enhanced it a bit.

This does the same thing, but does a little to handle errors and also tries to process built-ins.

qh uses () instead of {} so qh1() and out are local (in a subshell).

function qh () (
    function qh1 () {
      out="$(help "$1" 2>&1 )"
      [ $? -ne 0 ] && return 1
      echo "$out"
    }

    type -all "$1" ; { qh1 "$1" || "$1" --help 2>/dev/null || man "$1" 2>/dev/null ;} | egrep -i -- "$2"
) 

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.