Search code examples
bashbash-completion

Bash history expansion with tab completion


I make frequent use of command history expansion using the form !n:m, where n is the number of the historical command and m is the number of the argument, or short forms thereof.

Is there a way to expand such arguments in situ, so that I can then tab-complete them?

A trivial example:

$ mycmd long/path/with/plenty/of/subdirectories/
$ cp !$/tediously-verbose-filename.txt .

I'd love to be able to use argument repetition without having to then type the filename out in full (or resort to dummy runs with ls or echo).


Solution

  • The conceptual terms you're looking for is [command] history and history expansion - if you run man bash, you'll find sections HISTORY and HISTORY EXPANSION devoted to this topic.

    That said, in this particular case, it is not history expansion, but the special shell variable $_ that is your friend:

    It expands to the last (expanded) argument of the most recent command.

    Try the following, which mimics your scenario:

    ls "$HOME"  
    
    # Type this on the command line and press TAB (possibly twice)
    # _before_ submitting to TAB-complete to matching files in "$HOME"
    # (irrespective of what the current directory is).
    # $_ at this point contains whatever "$HOME" expanded to, e.g. "/Users/jdoe".
    cp $_/  
    

    Note: Whether tab-completion works for a given command is unrelated to whether $_ is used or not. See man bash, section Programmable Completion, for how to manually enable tab-completion for commands of interest.