A shell colon does nothing. Use it anyway
58 points by refp
58 points by refp
I had learned this trick years ago, if you have your prompt like this, you can quickly copy paste an entire line and it'll execute the command, ignoring the prompt bits.
: hayalci@tassadar ~/src/dool ; jj rebase -s dxw -d mrn
oh! That's nice!
Similarly, I stole something from plan9 where I use the autocd shell option and just have:
~/directoryname; <command>
This means if I copy my shell-lines it will continuously cd into wherever I actually executed the command.
In zsh, I use instead:
nbsp=$'\u00A0'
PS1="...$nbsp"
bindkey -s $nbsp '^u'
So I can paste the line with the special invisible non-breaking space, but this symbol will clear the line to the left.
I often use colons in Makefiles for pretty printing. You might be tempted to write Makefiles like this:
out/%.o: src/%.c
@echo CC $@
@$(CC) -c -o $@ $<
However I've had issues in the past where make spawns multiple echo process at a time which interfere with each other, since they're writing to the same stream. You could write this instead:
out/%.o: src/%.c
: CC $@
@$(CC) -c -o $@ $<
and now it's the make process itself that does the printing rather than a child process.
Ooh, this is a nice explanation. I saw this trick recently in a shell script, but didn't have time to look into how it works. It is also unfortunately very hard to find documentation, since man : or whatis : turn up nothing useful.
I suppose it's kinda like the true command, except that it definitely doesn't have special behavior for --help/--version/etc and it's fewer characters.
Why do you need the null command to force parameter expansion? Doesn’t it happen without the colon?
edit: Added a FAQ to the post.
The parameter expansion will happen regardless, but without a null-command or similar usage the shell will treat the resulting string as a command to run:
% ${HELLO:=123}
zsh: command not found: 123
% : ${HELLO:=123}
% echo $HELLO
123
Perhaps I should have included this explicitly in the article, your question is a very good one!
I use the null command all the time when I start typing something out but still want it in the history so I don't have to type it out again. Jump to the start of the line, add a colon, enter to put it in history and then do whatever else you were going to do, and later on jump back and just remove the first character to actually run it.
I never thought of using it for the side effect of evaluating the arguments though, that's clever!
An alternative way to achieve the same thing is by making it a comment (# instead of :). Has the (potential edge-case) advantage of not evaluating anything in there, if you're planning on doing so later. :)
And even better this is already available in bash & co: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-insert_002dcomment-_0028M_002d_0023_0029
I usually use <Esc>-# but the documented way is <Alt>-#. Comments the line and if repeated on a commented line it uncomments and executes the line.
In zsh you can use Meta-q (Alt-q?) to kill the current line to type another command, and yank it back to the command line buffer after the other command finishes.
some of us plebs still us bash 3 on macos (I do not know why I do this)
-bash: !}": event not found