Question

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).

Was it helpful?

Solution 2

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.

OTHER TIPS

Not exactly what the OP wants, but you could use readline shortcuts to retrieve a specific argument from a prior command, and the shortcut is Alt+.. For the specific example that OP gave, this works very well, with the following workflow:

$ mycmd long/path/with/plenty/of/subdirectories/
$ cp <Alt>+./tediously-verbose-filename.txt .

Here are a couple of additional things that I find very useful:

  • If you continue to press Alt+., it retrieves the last argument from prior commands in the history.
  • You can prefix Alt+. with Alt+<n> where n is a digit from 0-9 to retrieve the specific argument. E.g., Alt+0Alt+. would retrieve the command itself and Alt+1Alt+. would retrieve the first parameter etc. You can then continue to press Alt+. without having to repeat the prefix.

NOTE: On terminals where Alt combination doesn't work, you could use Esc prefix, e.g., <Esc>..

Yes, there is, use the following:

cp !$:h/tediously-verbose-filename.txt

The :h part will bring the directory portion of the command argument

I know this is old but looks like only option im seeing is running the command with :p to preview by printing to the screen, then arrow up in history to run it after editing.

I'm curious if a function could be created that pulls the results of !!:p then returns it to the line before the command is actually ran, initiated by a tab after !! for example. Ill post it here if i manage to figure out how to write it.

but here is the example of what i mean:

cd@PC:~> _ zypper install git
Loading repository data...
Reading installed packages...
'git' not found in package names. Trying capabilities.
No provider of 'git' found.
Resolving package dependencies...

Nothing to do.
cd@PC:~> !!:p
_ zypper install git
cd@PC:~> _ zypper install git-core
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top