Hacker News new | past | comments | ask | show | jobs | submit login

To make two copies of the last argument, so you can edit one of them in place, in Bash (or anything that uses GNU Readlne), simply do this:

   $ mv oldname _   # _ is your cursor
Now type Ctrl-W to erase the last word:

   $ mv _
Then type Ctrl-Y twice to yank it:

   $ mv oldname oldname _
Now edit in place as needed.

No utility needed, and just a regular mv command is issued whose inputs are completely recorded in the history.

Now,let's automate that. Add this line to ~/.inputrc:

   # ~/.inputrc entry
   \C-T: " \C-W\C-Y\C-Y\b"
Reload with

   $ bind -f ~/.inputrc
Now Ctrl-T does it:

   $ mv oldname_
Hit Ctrl-T

   $ mv oldname oldname_
How about having Ctrl-T end up on the first character of the name?

   # ~/.inputrc entry
   \C-T: " \C-W\C-Y\C-Y\b\eb"

I've been using bash/zsh for 18 years and did not know about ctrl-W, ctrl-Y. This might be a game changer for me!

Ctrl-W is the standard default character for erasing a word in the POSIX TTY cooked mode. Thus it works even when using programs that don't have a line editor. Ctrl-U similarly erases the whole line.

GNU Readline's key bindings for Ctrl-W and Ctrl-U mimic these actions for consistency.

Ctrl-U is very useful for retyping a botched password at the login: prompt.

getpass supports readline shortcuts? TIL

Is my comment not clear? They are not "readline shortcuts"; readline got them from Unix. GNU targeted Unix as the system to replace with free software and adopted its conventions.

Beside Ctrl-W and Ctrl-U, another convention from the Unix TTY found in readline is Ctrl-D.

getpass doesn't support editing at all; it runs the TTY in "cooked mode", just with echo disabled. The operating system kernel implements the rudimentary editing (Ctrl-W and Ctrl-U).

Note: ^T is also a very useful command bound by default to "swap the character under the cursor and the previous one". That is, `sl` followed by left arrow, ^T, produces "ls".

GNU readline is always surprising to me, being a Vi guy I almost always `C-x C-e` to edit my command with, you guessed it right: {,n}vi{,m}. But it seems that just taking the time to learn readline will be a very big boost in productivity.

You can add 'set -o vi' to your bashrc to enable a sort of vim emulation. Pressing Esc will take you to command mode, where you can use commands like b, w, e, 5x, i. Ctrl-w and ctrl-y still work as described here.

More importantly, if fixes the ctrl-w behaviour. By default c-w will delete up to the previous space. With set -o vi however, it deletes the same amount that vi considers a word to be. So if you're doing cd /a/long/dir and want to change it to /a/long/other/dir, pressing ctrl-w will only delete the last 'dir' instead of deleting the entire path. The default behaviour is highly aggravating.

I'm happy enough with `set editing-mode vi` in ~/.inputrc (for bash) and `plugins=(vi-mode)` in ~/.zshrc (for zsh).

Doesn't work if the filename contains spaces:

    # mv "Foo bar" _

No but the manual method with Ctrl-W still works. Multiple consecutive Ctrl-W operations add to the clipboard; you can gobble the whole thing with several Ctrl-W and regurgitate two copies with Ctrl-Y Ctrl-Y.

If you like spaces in filenames, you should use a GUI, anyway.

I recommend Windows Explorer; it's widely available.

Doesn't work for me if the filename has underscore(_) or dot (.) - it only copies part of the filename.

Ctrl-A, Alt-F, Ctrl-F, Ctrl-K, Ctrl-Y, Ctrl-Y


Ctrl-W Ctrl-W Ctrl-Y Ctrl-Y will work.

I would prefer to use brace expansion after learning about it today, over this.

Brace expansion won't work if you need to make edits in multiple places.

Well, it could work if we have a function to pick off the first and last combination from the Cartesian product, haha.

We define:

  # print first and last argument
  fl() {
   local a=("$@");
   printf "%s %s\n" "${a[0]}" "${a[${#a[@]} - 1]}"

  $ fl {a,b}--{c,d}--{foo,bar}--{x,y}--{m,n}
  a--c--foo--x--m b--d--bar--y--n
We can use this using command substitution, or the old backticks:

  $ mv $(fl path/{from,to}/subdir/{foo,bar}.png)
There we go; edits in multiple places.

I use escape-. a lot

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact