How can I move around the bash commandline efficiently?

19

20

So I use the up in my shell (Bash on OSX or Ubuntu, mostly) but some of the time I know that I want the stuff after the cursor's current location. Is there any way to have the line I'm on complete with the line above? Hitting up and then left is annoying.

Any other tricks would be cool too, except for tab, which we all now about :)

Here's an example (per ~quack's request):

I type mkdir /where/the/hell/is/that/thing and then I want to cd into the same directory. But now I know about meta-b :)

Dan Rosenstark

Posted 2010-02-24T22:05:47.343

Reputation: 5 718

1an explicit example would be awesome. – quack quixote – 2010-02-24T22:39:09.353

@~quack doing example now – Dan Rosenstark – 2010-02-25T01:06:06.273

1

here's a related (duplicated) question, with a quite nice answer: http://superuser.com/questions/124336/mac-os-x-keyboard-shortcuts-for-terminal/124367#124367

– cregox – 2010-04-13T19:44:58.273

Answers

11

Try this:

mkdir /where/the/hell/is/that/thing

then press alt+.

depending on your OS and terminal you might have to type esc then .

You can also press alt+1+. to pick a specific prior argument.

This is much better than !! or !$ because you can actually see what you are about to run, and it takes less keystrokes anyway.

edit: strictly speaking it is meta not alt, so it might also work with the "windows" key depending on how your keyboard is setup..

user23307

Posted 2010-02-24T22:05:47.343

Reputation: 5 915

interesting! didn't know about that one. – quack quixote – 2010-02-25T01:53:53.570

2@justin this is awesome. On OSX meta is escape. – Dan Rosenstark – 2010-02-25T18:45:53.637

@yar with OS X Terminal there is also a preference setting under 'Settings' -> 'Keyboard' to 'use option as meta key'. – ThomasW – 2012-10-05T02:34:12.263

Thanks @ThomasW I gotta get back to this stuff. I'm on the command line daily, but use very little of the tricks. – Dan Rosenstark – 2012-10-05T20:13:24.180

28

You should read through man bash on your system, particularly the section on Readline, as this is bash's interactive input mechanism. The Bash manual at gnu.org has a nice section on Commandline Editing that will help fill in some of the gaps.

By default, you can use these to move around on the commandline (just listing a few here; see the link for a full list):

  • Ctrl+a moves to the beginning of the line (or Home depending on terminal settings)
  • Ctrl+e moves to the end of the line (or End ...)
  • Meta+f moves forward a "word"
  • Meta+b moves backward a "word"

You can use these to "kill" (aka "cut") text from a line:

  • Ctrl+k kills ("cuts") text from the current cursor position to the end of the line
  • Ctrl+y yanks ("pastes") the most recently killed text back into the buffer at the cursor

So you can combine these to select a chunk of some commandline you want to repeat, kill it, then paste it to the end of your next command.


Now, to make it even more fun, let's consider bash's History Expansion. This is that !! that Studer's answer mentions. History expansion breaks down into event designators, word designators, and modifiers.

Event designators look like this (again, see the links for the full list):

  • ! - starts a history substitution
  • !n - the n-th command in bash's history list, for some integer n (works for negatives too)
  • !! - the preceeding command; equivalent to !-1
  • !string - the most recent command starting with string

Word designators select certain parts from an event. Use : to separate the event from the word designator. Words are numbered from 0 starting at the beginning of the line, and inserted into the current line separated by single spaces.

  • $ - designates the last argument (eg !!:$ is the last arg of last command; can be shortened to !$)
  • n - designates the n-th word (eg !str:2 is the 2nd arg of the most recent command starting with str; !!:0 is the command of the last command)

So, to follow up on your example, if your last command is mkdir /some/really/long/path, just running !! will rerun that command again. But you want to cd into that path instead:

$ cd !$

Now let's say you perform some other commands and then want to refer back to that path again. If that was the last mkdir command you ran, you can use this to repeat that path:

$ tar czf ~/foo.tgz !mkdir:$

quack quixote

Posted 2010-02-24T22:05:47.343

Reputation: 37 382

you can also bind these (and other Readline commands) to whatever key combinations you like; see section 8.4 of the manual, Bindable Readline Commands: http://www.gnu.org/software/bash/manual/bashref.html#Bindable-Readline-Commands and section 8.3, Readline Init File: http://www.gnu.org/software/bash/manual/bashref.html#Readline-Init-File

– quack quixote – 2010-02-24T23:02:19.127

thanks that really helps. Although "read the manual" was kind of expected, mentioning the basic moving around bindings does help. Even just knowing ctrl-a might be real savings. – Dan Rosenstark – 2010-02-24T23:06:40.410

@quack, no problem, I caught a later revision, in fact :) – Dan Rosenstark – 2010-02-25T00:59:00.797

1also note bind -p or bind -P will print your current keybindings; that's the ultimate reference for what your bash uses. – quack quixote – 2010-02-25T01:52:51.870

1I think this answer has grown: the stuff on History Expansion is great. – Dan Rosenstark – 2010-04-14T09:46:36.957

@quack quixote Where is the Meta Key or does it have some implicit meaning that I am missing here? – Geek – 2013-08-03T05:56:31.670

6

If you're a vi user you can put the shell into vi mode by typing set -o vi.

You can then do all kinds of powerful things on the command line after typing Esc + k.

The one I use the most is Esc+K then / any text typed after the slash will be used to search through your command line history.

e.g. Esc + k /smbclient will give the last smbclient command you typed. You can scroll through all the searches using standard vi keys (j and k for up and down but I think up and down arrows will work too).

Further help here, there are also some inbuilt bash things at that link which might be more what you're looking for.

Cheers, Stu.

Stuart Brock

Posted 2010-02-24T22:05:47.343

Reputation: 176

while vi mode is useless to me, since I haven't yet stepped up to vi, the l ink is awesome. Thanks for that! – Dan Rosenstark – 2010-02-25T01:03:16.117

1The equivalent without vi mode is ctrl-r. Type it, and then part of a previous command. It will bring up the last occurrence of what was typed. Hit ctrl-r again to get to the next one. Very handy. – Nerdfest – 2010-02-25T01:25:39.327

3

You can use !! which represents the last command :

% test
% echo !!
> test

Studer

Posted 2010-02-24T22:05:47.343

Reputation: 3 448

interesting. Not sure that I want to then manipulate that string using...what? – Dan Rosenstark – 2010-02-24T23:07:26.960

this is part of bash's history facilities: http://www.gnu.org/software/bash/manual/bashref.html#Using-History-Interactively .. particularly the history expansion: http://www.gnu.org/software/bash/manual/bashref.html#History-Interaction ... note !! is a synonym for !-1: http://www.gnu.org/software/bash/manual/bashref.html#Event-Designators

– quack quixote – 2010-02-24T23:32:28.273

2>This is really useful for when you forget to use sudo: i.e. sudo !!

$ more /etc/sudoers /etc/sudoers: Permission denied $ sudo !! sudo more /etc/sudoers [sudo] password for ..:

/etc/sudoers

... ... ... – user9632 – 2010-02-25T01:36:49.320

@wookiebreath, thanks for that, I'll vote this answer up now – Dan Rosenstark – 2010-02-25T18:46:27.770

0

In the example you give, use !$ to represent the last parameter of the previous command:

mkdir /something/somethingelse

cd !$

You can also use numbered variations to pull out specific parameters of previous commands.

Nerdfest

Posted 2010-02-24T22:05:47.343

Reputation: 808

0

I recently found this readline cheat-sheet very useful. Lots of things I didn't know. I used to use !$ all the time until I found out about Alt+., which I now use all the time. :)

fredden

Posted 2010-02-24T22:05:47.343

Reputation: 286