Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am not sure how to word this, but I often I find myself typing commands like this:

cp /etc/prog/dir1/myconfig.yml /etc/prog/dir1/myconfig.yml.bak

I usually just type out the path twice (with tab completion) or I'll copy and paste the path with the cursor. Is there some bashfoo that makes this easier to type?

share|improve this question
    
I think you mean bash-fu :) – cat 17 hours ago
up vote 35 down vote accepted

There are a number of tricks (there's a duplicate to be found I think), but for this I tend to do

cp /etc/prog/dir1/myconfig.yml{,.bak}

which gets expanded to your command.

This is known as brace expansion. In the form used here, the {} expression specifies a number of strings separated by commas. These "expand" the whole /etc/prog/dir1/myconfig.yml{,.bak} expression, replacing the {} part with each string in turn: the empty string, giving /etc/prog/dir1/myconfig.yml, and then .bak, giving /etc/prog/dir1/myconfig.yml.bak. The result is

cp /etc/prog/dir1/myconfig.yml /etc/prog/dir1/myconfig.yml.bak

These expressions can be nested:

echo a{b,c,d{e,f,g}}

produces

ab ac ade adf adg

There's a variant using numbers to produce sequences:

echo {1..10}

produces

1 2 3 4 5 6 7 8 9 10

and you can also specify the step:

echo {0..10..5}

produces

0 5 10
share|improve this answer
    
damn thats sweet. I figured I wasn't the first to ask, just kind of a tricky question to word. – user1028270 yesterday
    
What does the comma do there? – user1028270 yesterday
4  
See Brace Expansion in the manual: it separates values used in the expansion. Here the two values are the empty string and .bak. – Stephen Kitt yesterday

History expansion can be useful for this kind of thing (assuming bash history is enabled).

In your example, you could do:

cp /etc/prog/dir1/myconfig.yml !#:1.bak

Here, the !# refers to the current line, !#:1 refers to parameter 1 on the current line,
and !#:1.bak refers to parameter 1 on the current line with '.bak' tacked onto the end.

When you have the history specifier typed out, you can use Ctrl+Alt+E to expand it to its actual value if you want to e.g. double check or modify the filename.

The "History Expansion" section in the bash man pages has more info.

share|improve this answer

Similar to progo's answer, but somewhat simpler: C-w cuts (“kills”) the word to the left of the cursor, C-y inserts (“yanks”) it again.

$ cp /etc/dir1/myconfig.yml█                              (C-w)
$ cp █                                                    (C-y)
$ cp /etc/dir1/myconfig.yml█                              (space, C-y)
$ cp /etc/dir1/myconfig.yml /etc/dir1/myconfig.yml█       (finish text)
$ cp /etc/dir1/myconfig.yml /etc/dir1/myconfig.yml.bak█
share|improve this answer
2  
Also worth noting that you can do this with multiple words in a row (if your filename has spaces, for example) and C-y will paste all of them, as long as you haven't moved the cursor or typed anything else in between. Any mix of deletion commands except single-character deletions (e.g. backspace/del/ctrl-d) works with this. – Random832 13 hours ago

You can also actually cut-paste (kill-yank in emacs/bash terms) from the commandline to duplicate parts for editing.

M-d kills forwards until word boundary, and you can kill text multiple times and they all get concatenated together to a single 'paste' for yanking. Convenient!

Yank this all back to the commandline at cursor by C-y. So if you have a line like this (the block element █ indicates cursor position):

$ cp avb.txt█                 (M-b M-b)
$ cp█avb.txt                  (M-d) kill the word 'avb'
$ cp █.txt                    (C-y) yank it back
$ cp avb█.txt                 (C-e) to the end of line
$ cp avb.txt█                 (C-y) yank it again
$ cp avb.txt avb█             finish the line
$ cp avb.txt avb.foo█

Either way you prefer to do it, familiarizing yourself with what bash has to offer in interactive key department will be beneficial. http://web.mit.edu/gnu/doc/html/features_7.html

share|improve this answer

In tcsh or zsh, Alt+Ctrl+_ in emacs mode (copy-prev-word widget) inserts the last word, so

cp very-long-path Alt+Ctrl+_.back

bash has a copy-backward-word widget (not bound to any key by default) but that only copies the word to the ring buffer, you'd need to also press Ctrl-Y (in emacs mode) to yank it. But you could do:

bind '"\e[cpw~": copy-backward-word'
bind '"\e\C-_": "\e[cpw~\C-Y"'

To have Alt+Ctrl+_ do both the copy/snarf and paste/yank like in tcsh/zsh.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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