27 comments

[ 2.1 ms ] story [ 46.4 ms ] thread
Rather than a sense of "cool" or "useful" somehow I end up just feeling despair at how organically convoluted it is to determine what something on a command-line really does. To be fair, I've always been biased towards "only the simplest scripts should be in shell languages."

This also adds an intriguing new dimensions to reviewing/verifying shell commands as benign and correct... How long until LLMs start (ab)using the trick in little requests they want me to approve?

If you really want to be lazy, use a terminal file manager (I prefer lf[0]) it helps avoiding the cd && ls dance. That way, your history only contains commands you actually would want to rerun.

0: https://github.com/gokcehan/lf

sigh The usability of ! versus Ctrl+R in a shell is pretty much the same as the usability of ed versus vi, or moving files around using cp/mv versus using Midnight Commander or the like: in the first case, you have to accurately remember the past (which for many people is pretty difficult); in the second case, you don't have to, because you always have an immediate view of the state of the system and the preview of the effect you're about to incur.

And yeah, I've done editing with ed; it definitely beats "cat >file.txt" and copying parts around with head/tail and retyping the corrections manually, sure, and it works in every environment that can take line-oriented input from the user (so, literally everywhere), but that's about as much praise as I can give it.

Every time someone brings this up, I think "oh right, I could do that" and then immediately forget. Especially if you can type quickly, it's easier to just "drive straight ahead" with the command you want, than add another "mental branch" to interrupt the flow. For the same reason I'll often Ctrl+C and start again instead of trying to backspace and correct.
> For the same reason I'll often Ctrl+C and start again instead of trying to backspace and correct.

Try ctrl-x ctrl-e to edit the command in your choice of editor ($EDITOR).

Editing commands is not hard with a few keys. At least learn alt-b and alt-f to go a word back or forward. Often ctrl-left and ctrl-right will do the same thing easier (depends on your terminal). Ctrl-w deletes back to the previous space, alt-backspace and alt-d delete the previous and next word respectively. There are many more keys in the manual, but those cover most things.

this is overkill and way slower for most short commands. And you still need to scroll to wherever you need to edit. doesn't save anything, really.
If you use vi or emacs you can edit directly using the bash/readline editor.

(Or if you use emacs, then you already have a full editor in your shell)

Everyone need be aware, bash uses emac extensions by default. As I refuse to use emacs, I therefore refuse to use these extensions in bash!

In as most sensible people use vi, don't taint yourself by touching this foul and evil emacs magic. Being known as an emacs user could cost you a job, shorten your career, or even cause rifts with family and friends.

Instead my friends, if you must use such bash shenanigans, switch it to vi extensions. You'll feel better about yourself, stand taller, and be a better human being as a result.

Be safe.

It’s a funny comment, but it’s also sort of true. Back in the stone ages I had to go from Solaris to sunOS to QNX to Unixware to HPUX to Linux to BSD (maybe freeBSD was in there too) and many others that I can’t remember. Oh yea, Irix, too. This is all in a 2 year period. Vi was the only editor that was on all of these machines so I (to this day) could never be bothered to learn anything else.
! calls are vital for your sanity if you ever do remote support

trying to write shell commands on a hypervisor console window within a remote session on a jump box is excruciatingly laggy and annoying, and that's assuming your remote session connection to the client is behaving well in the first place

If you find this interesting, don't wait for a random blogpost to appear by chance on HN, go read some manage today!
i love the mkdir example, so i’m going to exercise that muscle and see where it goes

and yeah ^r works, though i often type a few chars and ^p till i get the match. history-search-backward in your inputrc, iirc

edit: on a computer now :) my `if emacs` block, allowing arrows or ^n/^p to run through history. so for e.g., type "tar" and now as you shift through history with :binding:, it only shows history that began with "tar"

    $if mode=emacs
    "\e[A": history-search-backward
    "\e[B": history-search-forward
    "\C-p": history-search-backward
    "\C-n": history-search-forward
    ...
    $endif
Very annoying prose.
I’ve been burnt before using ! and forgetting what command I typed previously, thus invoking the wrong command line.

!! is handy for the sudo example, but beyond that, I tend to prefer pressing the up arrow to cycle through the history rather than picking the first item. Eg:

  !ssh
vs

  ssh[up]

It’s the same number of key strokes but less error prone
Not knowing what command you are doing before you submit it is poor design. There are alternative ways to access old commands where you can see the actual command you are about to run before you submit it. The physical teletype era is over.
You can add :p to print the command.
> Not knowing what command you are doing before you submit it is poor design.

For this reason I recommend avoiding using history expansion features with any commands in history that might destructively modify file contents, such as `find ... -delete` in GNU find.

In the default Bash Emacs readline bindings, you can type Alt/Meta-^ to expand history on the current line without executing. You can also set `shopt -s histverify` to expand the history substitution on the following line after pressing enter/submitting the history substitution and it also does not execute the command.

I'm much too lazy to memorise what all of these do, I'd rather just use fish wherever I can. Some combination of typing, arrow keys, and alt+arrow keys is always enough for me to find that thing I want to avoid fully retyping.

P.S. The alt+s shortcut is much quicker than writing sudo !!

Decades ago, I was taught to use `!` and Co, by a Linux user who was fond of the `sudo !!` trick. Then I switched from this implicit interpolation to explicit shortcuts, and I'm glad I did.

As suggested in the FAQ at the bottom, instead of !… you can use ctrl-r. Or better, optionally type the first letters then alt-p or "up". It's more powerful and more extensible. Other shortcuts, like alt-., allow navigating into the past parameters.

With up, alt-p, alt-. and such, the command line displays the real command. The !… magic is more error-prone and ambiguous; with zsh, I'd suggest hitting TAB to expand the magic into a static text.

I would add other entries to the FAQ: When I enter `sudo !!` will it be stored unchanged in the shell history, or stored after interpolation of `!!`? When I start a command line with a space, so that zsh does not put it in the shell history, will !… also ignore that line? Is `!$` recursive?

This is for teletypewriters. For those of us with interactive electronic video displays, we can use up-arrow to recall the last command or Ctrl-R to search history, then edit the recalled command.
And for editing that command line... I know a lot of people who know about Ctrl-a, Ctrl-e, Ctrl-k, but still hold down the left arrow key or delete key a lot to edit things in the middle.

Those people want to use:

    Alt-f    move cursor forward one word
    Alt-b    move cursor back one word
    Alt-d    delete to the end of the next word
    Alt-Del  delete backwards to the start of the previous word

    Ctrl-_   undo
Here's a cheatsheet: https://readline.kablamo.org/emacs.html
> who haven't wished they could edit their long commands in an editor rather than in the shell?

That's called a shell script. I don't know what others thresholds are but mine is about three pipelines deep(or 80 characters whatever comes first) and I am going to write that son of a gun as a script. Mainly to have something named in the filesystem I can edit, same with my sql queries, I have a whole directory of long awkward mostly one off queries, psql has the \e command which helps but again I would rather have something named.

I got used to doing this over many many years with the tcsh shell. I switched to Fish recently and I continue to be annoyed by its refusal to implement this feature. Yes, I tried using all the newfangled history-search thingamajigs. They all kind of work, and they all have their issues. But the !, together with in-place expansion, is something I still dearly miss.
(comment deleted)
> alt-. is great for what it is designed to do, iterating over the previous "last arguments" of your shell history. It's great at doing that, but it is also limited to doing just that one thing.

No, it isn't limited to just that. Alt-0 alt-. will give you the zeroth "argument" (the program), alt-1 alt-. will get you the next (the program's first argument), etc. Negative arguments count back from the end: alt-- 1 alt-. will get you the argument before the last one (note that alt is held for the "-" but not the digit).

When you do use event designators, ctrl-alt-e (or alt-^) is critical. It expands all the ! codes inline to what they refer to, so you can see what you're doing before you hit enter, and as you're constructing the command too.

IMO, !$ is most useful of them all (it is the one that gets replaced with the last argument of the last command).

!! you can do just as easily with up-arrow enter, which is just as quick. !ssh you can do with ctrl+r, which actually shows you what it's going to run and whether the last ssh is to where you think it is. sudo !! is up arrow, ctrl+a, 'sudo ', one more keystroke but it's natural if you know your readline. The rest are too complex and not worth learning. !$ is the sweet spot.