23

I was just typing something along the lines of:

mv foo/bar/poit/zoid/narf.txt

and suddenly realized, damn, I have to type large parts of that parameter again

mv foo/bar/poit/zoid/narf.txt foo/bar/poit/zoid/troz.txt

Even with tabcompletion, quite a pain. I know I can copy paste the parameter by mouse-selecting the text and middleclick but that is not good enough. I want to remain on the keyboard.

So is there a way to copy paste the current parameter of the line using the keyboard?

  • 3
    My advice doesn't answer your question, but is a small tip. As in your example, you can use next construction: mv foo/bar/poit/zoid/{narf.txt,troz.txt} instead ot typing/copypasting long address twice. – rush Jun 6 '12 at 10:05
  • 2
    Slightly shorter than @Rush's solution: mv foo/bar/poit/zoid/{narf,troz}.txt. This works especially well if we have something like .../zoid/this_source_file_has_to_be_patched.c{,.orig} – Ansgar Esztermann Jun 6 '12 at 10:14
  • @Rush Do you mind pointing it out as an answer? It may not be directly what I asked, but then again, your solution is much more to the point of what I want. It deserves a token of acceptance. – k0pernikus Jun 6 '12 at 10:21
13

If I've planned ahead, I use brace expansion. Here is another approach using the default readline keyboard shortcuts:

  • mv foo/bar/poit/soid/narf.txt: start
  • Ctrl-w: unix-word-rubout to delete foo/bar/poit/soid/narf.txt
  • Ctrl-ySpaceCtrl-y: yank, space, yank again to get mv foo/bar/poit/soid/narf.txt foo/bar/poit/soid/narf.txt
  • Meta-backspaceMeta-backspace: backward-kill-word twice to delete the last narf.txt
  • troz.txt: type the tail part that is different

If you spend any non-trivial amount of time using the bash shell, I'd recommend periodically reading through a list of the default shortcuts and picking out a few that seem useful to learn and incorporate into your routine. Chapter 8 of the bash manual is a good place to start. Knowing the shortcuts can really raise your efficiency.

  • Neat! In my case I had to press Alt + Backspace instead of Meta + Backspace. – k0pernikus Jun 7 '12 at 9:44
  • 3
    @k0pernikus Yes on most keyboards, the Alt key is the Meta key. – jw013 Jul 12 '12 at 16:19
24

History expansion actually works on the current command as well, using the event designator !#. Combine this with the word designator for the last argument - $ - to get the parameter you just typed. And you can use all the regular modifiers over it, so if, e.g., you are renaming a file in a far away directory, you can just type:

mv path/you/do/not/want/to/type/twice/oldname !#$:h/newname
  • Very useful! This works especially well with bash's magic-space option in inputrc to automatically expand history expansions. (I couldn't use the top-voted answer because I've set ^W to break at slashes since that's usually more useful.) – Soren Bjornstad Jan 22 '16 at 17:40
  • @SorenBjornstad alt+backspace usually already stops at word delimiters like slashes, so you needn't change how ^W to get that functionality, you can have both delete non-word-character or whitespace delimited words – Eric Renouf Dec 17 '16 at 13:13
  • 1
    This is the correct answer to this question. Please update. – hackel Apr 27 '17 at 20:21
14

As in your example, you can use next construction:

mv foo/bar/poit/zoid/{narf.txt,troz.txt}

or even (as suggested Ansgar Esztermann):

mv foo/bar/poit/zoid/{narf,troz}.txt

instead ot typing/copypasting long address twice.

6

Playing around I got this to work:

mv foo/bar/poit/zoid/narf.txt

Hit Enter
to store the last parameter.

Now use to get last typed in line back. Enter a space and to get the last used parameter use:

Alt + .

I hate provoking an error, but it gets the job done in this use case.

  • Cool, another great tip learned! – Bram Jun 6 '12 at 18:07
  • <kbd>Esc</kbd> + <kbd>.</kbd> is (it?) the same as <kbd>Alt</kbd> + <kbd>.</kbd>. – Nikos Alexandris Jul 15 '13 at 10:19
  • I don't know whether to say "thank you" or "lol" – user7000 Nov 19 '18 at 22:15
2

You can easy use variables:

a=test.csv ; cp $a $a.bak

Or in you case (note tab competition works for the a part):

a=foo/bar/poit/zoid/ ; mv ${a}narf.txt ${a}troz.txt
2

A short interactive solution two steps solution:

1. type: echo foo/bar/poit/zoid/narf.txt

This makes foo/bar/poit/zoid/narf.txt avaylable for the Alt-. shortcut in bash.

2. type: mv and hit Alt-., Space, Alt-.

You will get mv foo/bar/poit/zoid/troz.txt foo/bar/poit/zoid/troz.txt. Now you can modify the last word easily.

A tool, which might come (very) handy is:

Midnight Commander - a file manager running in the console. It gives you the possibility to copy filenames and directory paths interactively into the command line. Midnight commander shows you therefor 2 panels (left and right), which list the content of different directories.

A short guide:

  • Up Down arrow keys select files in the current panel.
  • Tab switches between left and right panel.
  • Ctrl-Shift-Enter copies the currently selected file to the command line (including full path)
  • Alt-o opens the currently selected directory in the other panel
  • Ctrl-o lets you see the console in full screen
  • Ctrl-xp copies the path of the active panel into the console
  • Ctrl-xCtrl-p copies the path of the inactive panel into the console
  • Esc-Tab is auto completion

This is by far the fastest way I found so far - after one got used to the shortcuts.

2

I have this in my ~/.inputrc:

"\ej":"!#:$\e^"

!# is the current line, :$ is the last word, and \e^ is history-expand-line.

  • this should be marked as the answer. Pressing 'alt/option + j' now copies the last word. – mpprdev Nov 15 '17 at 3:02
2

For zsh, I find the following keybindings helpful.

# Bind alt-m to insert previous word from the current line
bindkey '^[m' copy-prev-shell-word

# Bind alt-k to kill word before cursor in vi-style
bindkey '^[k' vi-backward-kill-word

So I hit Alt-M to repeat the last argument then Alt-K if I want to delete parts off the end of a path.

Here's a useful reference to some of the behaviors you can map.

0

Use the same thing in the {,} "duplicator". I.e.:

git tag -m {v,v}1.0.1

# same as 

git tag -m v1.0.1 v1.0.1

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.