You know how there are weird tricks with computer stuff that you think everyone knows but they don't? I live learning and teaching new things like those when they come up.

Today's was the carat substitution in bash. It probably works in other shells too but IDK, I'm too old to learn a new shell.

The way it works is fairly similar to the / in sed or similar. You can use them to run the previous command but with a string substitution.

For example, let's say I entered this command:

dig A cascadiacrow.org

When it fails to resolve, I realize it was a .com domain. Rather than retyping the command, or hitting the up arrow to change the previous command, you could do this:

^org^com^

And it would run:

dig A cascadiacrow.com

Kind of cool with those one liners you spend way too much time on and find a typo.

Anyway, I used it and someone thought it was magic so if it's new to you too, happy Monday.

reshared this

in reply to Bruce Heerssen

@bruce @bob_zim Speaking of history, at least in bash, if you put one or more spaces before your command, that command does NOT get saved to your command history. 👻

This is sometimes useful when you have to repeatedly run a very long command and then want to do a one-time test of some variation of it without breaking your "up+enter" flow.

in reply to :rainbowCrow:

I like using $_ in bash

It refers to the final argument of the last command, useful when such argument is very long, like:

mkdir /var/log/very/long/dir/path
chmod 2750 $_
cd $_

There $_ holds /var/log/very/long/dir/path

When writing this, I was thinking that something feels special about it, and just remembered that this is a trick that a human being taught me years ago, not something I read in a manual.

in reply to don Elías (como los buses) 🥨

@donelias
Fun fact: on the surface, both `!$` and `$_` seem to do the same thing, pop the last argument of the previous command, but the former brings it up **after shell expansion** while the latter brings it up **before shell expansion**.

For example:
```
~$ ls fooba*
test1
test2
test3
~$ ls !$
test1
test2
test3
~$ ls $_
ls: fooba*: No such file or directory
```
Or even more speaking:
```
~$ echo "$(date -z UTC)"
Tue Jul 14 14:48:25 UTC 2026
# wait a few seconds
~$ echo 'With $_\t' $_ '\nWith !$\t' !$
With $_ Tue Jul 14 14:48:25 UTC 2026
With !$ Tue Jul 14 14:48:39 UTC 2026
```
Here, `$_` was expanded to what was actually received by the command, whereas `!$` was expanded to what you actually typed, before the shell interpreted it.

@cR0w

in reply to :rainbowCrow:

@wollman Interactively, I still use tcsh (which I believe added to csh in-place command-line editing and a few other things bash brought into sh-land), almost entirely because there’s no way to make bash not beep when there are multiple possible auto-complete options. For any actual scripting, I (mostly) use bash.
in reply to :rainbowCrow:

if you type Alt+Dot (or Esc,Dot), it shows the previous command's final argument. Do it again for the command before that.

Alt+{2,Dot} (holding Alt, press 2 then Dot) gets the penultimate argument. Keep holding Alt so you can press Dot to go to older commands.

#bash & #zsh. Note, some terminals don't support the Alt implementation. Esc can't enumerate.

#bash #zsh
This entry was edited (today, 5:38 AM)
in reply to :rainbowCrow:

> I'm too old to learn a new shell.
Progression be like:
I'm too old to learn anew.
I'm too old to learn.
I'm too old.

edit: by the way, the string substitution in bash is probably the Never Ending Story (wouwo wouwo wouwooo) in terms of how many ways one can do that.

And yes, i didn't know that one. Handy 👍🏻

This entry was edited (today, 6:58 AM)
in reply to :rainbowCrow:

This is a cool trick!

One note: When I shared it, one of my followers felt like there was an implication here that Bash/shell scripting is more widely used than it is. (The xkcd "we forget most people only know x, y, and of course z" strikes again).

Would it be possible to rephrase this slightly to emphasise this toot is specifically targeted at people who know Bash?

This entry was edited (today, 1:47 PM)
in reply to jordan

@jordan I had that issue upgrading Ubuntu to 26.04 (from a much older release), which moved from GNU to UUtils Coreutils but forgot to install the replacement. I went to the old standby of echo * but then also remembered that Debian systems all include BusyBox. Just run busybox ls instead.

This was essential as various dpkg post install scripts needed ln, cp, rm, and more, so I temporarily symlinked (busybox ln …) these commands, in /bin, to busybox. Voila, the upgrade could complete.

in reply to :rainbowCrow:

Have you got a window somewhere off screen in Windows, where you can't grab it with the mouse to drag it around?

This has worked since windows 3.x, possibly earlier: Alt+Space, m, tap an arrow key, then move your mouse. Tapping an arrow key "sticks" the window to your mouse cursor.

If this didn't work, the window might be maximized and needs to be Restored first: Alt+Space, R. Then do the above.

in reply to Richard "mtfnpy" Harman (he/him)

@xabean Use this all the time! Before they removed the feature, I also used to use "Cascade Windows" from the task bar when this happened.

The cascade button also worked for hidden dialog boxes. Still haven't found a replacement for that trick with regard to those.

in reply to :rainbowCrow:

I hope everyone knows ctrl-a throws you to beginning of the line & ctrl-e to the end.

> + I was too lazy for any of the "sudo !!" solutions, I mostly realize that I forgot sudo _while_ typing the command. So bound that to double-esc (also brings last command if prompt is empty):
zsh: paste.gurkan.in/nonundulating-…
bash: paste.gurkan.in/unconcentrativ… (not tested as much, only if I have to :hidethepain: )

This entry was edited (today, 4:55 PM)
in reply to :rainbowCrow:

I want to throw {} expansion into the ring:
E.g `ls file.{c,h}` expands the file argument once with c, then with h, so effectively running `ls file.c file.h`.
Very useful for comparing the same file in different folders: `diff -u {old,new}/somefile.ext`.
And much more targeted than most globbing, e.g. `git add file.*` usally complains about my vi backup files but `git add file.{c,h,proto}` targets exactly what I want.
in reply to :rainbowCrow:

infosec.exchange/@BednarTildeO…


RE: infosec.exchange/users/BednarT…

in reply to :rainbowCrow:

I learned this trick in the early 1980s at DEC, from Ken Arnold, who was in my department. Except Ken used the comma character instead of carat, saving a few keystrokes. The magic in .login is:

set histchars=\!,

(cshrc / tchsrc syntax, not bash.) I have carried this incantation forward in all my Unix-like environments for 40+ years.

This entry was edited (today, 6:11 PM)
in reply to :rainbowCrow:

Let's say you have two container runtime engines but you want to prefer one over the other:

which podman docker | head -n1

This will prefer whichever is first in the list, podman, in this case. Why is it useful? Say you're creating a Makefile and you need to interact with a container. Some people use podman and others use docker. In your Makefile you can put:

CONTAINER_RUNTIME ?= $(shell which podman docker | head -n1)

Then you can refer to $(CONTAINER_RUNTIME) in the Makefile target to use either podman or docker, (or something else, but that's for another toot).

(as a disclaimer, I work for Red Hat, which maintains Podman, but I do not work on that team.)

in reply to thedoh 🇨🇦

Another one:

Let's say that you sometimes have to paste sensitive things into your terminal, like login strings, or credentials.

If you paste them in normally, they'll show up in your history, and that could be bad. That can be mitigated to some extent in Bourne shell with:

export HISTCONTROL=ignorespace

Now, you can put a leading space in front of your sensitive command and it won't show up in your history:

` curl -u username:password https://www.example.com/login`

(put in backticks to make it obvious there's a leading space)

in reply to :rainbowCrow:

My favorite that most people don't seem to know is that substitution in sed (and vim) doesn't require slashes.

Most people use something like 's/search/replace/'

But you can use any character for the delimiters, such as: 's#search#replace#'

This is very handy when editing paths or anything else with slashes in the search or replace text.

This entry was edited (today, 6:51 PM)

This website uses cookies. If you continue browsing this website, you agree to the usage of cookies.