CLI tricks every developer should know
github.blog
github.blog
Everything but the last argument:
% git add -p dir1
% !!- dir2
git add -p dir2
Everything but the command: % textadept a b c
% vim !*
vim a b c
Substitute a string (once): % echo helo world
% ^lo^llo
echo hello world
First and last arguments: % diff path/a/file path/b/file
% diff !$ !^
diff path/b/file path/a/file
A cool detail is that even a long quoted string containing spaces is considered a single argument, and it all works fine.Also, the bangs can be anywhere on the command line, even inside other kinds of expansion; history expansion has highest priority of all.
Edit: the above is csh-style history expansion, available in bash as well.
Here's a more detailed article I wrote about them a while back:
https://www.masteringemacs.org/article/keyboard-shortcuts-ev...
For instance, did you know that you can record keyboard macros and play them back? It's a GNU readline feature.
set -o vi
If you're already familiar with Vi, Vim or NeoVim then it's a really comfortable way to work.That would certainly explain this error message I'm getting in Powershell
`Get-History : Cannot bind parameter 'Id'. Cannot convert value "n" to type "System.Int64". Error: "Input string was not in a correct format."`
https://github.blog/wp-content/uploads/2023/04/bash-screensh...
A bit click-baity and could deserve a bit more introduction of what it is (shell). But the list of shortcuts is nice to add to your toolbox, if not already there.
You can get the same on Windows by using WSL, or out of the box in Linux (usually).
When editing a command line, it deletes the character under eh cursor.
When reading from stdin, e.g., if one executes cat with no arguments and not in a pipeline, it acts as EOF and ends the read. Interestingly enough, if entered after text without a newline, it ends that segment of input; entering it again ends the read.
Ctrl-u and Ctrl-k delete from the cursor to the start and end of line respectfully; ctrl-w deletes from the cursor to the start of the current word.
Alt-b and Alt-f move backward and forward one word. Very handy.
Now it's for all developers!
% echo $SHELL
/bin/tcsh
% echo "the date is $(date)":
Illegal variable name.
The article doesn't even use the word "Unix": "For this blog post, all of the examples are for Bash since it’s the most widely used shell. And if you’re using Windows, Windows Subsystem for Linux (WSL) is available if you’d like to use a Bash terminal."For which OS was tcsh originally developed?
Tcsh started as a fork of csh, adding filename completion. https://en.wikipedia.org/wiki/Tcsh
See https://en.wikipedia.org/wiki/C_shell for why csh was popular over the Bourne shell of that era.
Why do you ask? Is it a trick question in that it has influences from TENEX?
mkdir /tmp/foo # /tmp/foo is the last token
cd <esc .> # cd /tmp/foo is the result
touch bar.txt # bar.txt is the last token
vim <esc .> # vim bar.txt is the result
:wq # ...exit vim
ls <esc .><esc .> # two tokens previously gets you to "ls /tmp/foo"
It's kindof like an "it" variable. Another "trick" I use often is `fc` and related: `help`, and the humble `#` comment character. # `fc` - mnemonic: "Fix Command"
cp -rv /tmp/foo /tmp/bar # ...but don't press enter!
<ctrl-a> # <enter> # beginning of line, comment it out, commit to history
fc # now you can edit to your heart's content
man fc # it's a builtin
help fc # and builtins have documentation via "help"
man cd # going to the "builtins" manpage is not that useful
help cd # ...did you know cd supports -L and -P ??
...and a slightly related vim-tip in the context of "fc". `<shift-v>:!ls /tmp` is an interesting technique to "bring in" the output of a command for editing.Example:
git commit -m "whoops, don't commit just yet (don't press enter)"<ctrl-a>#<enter>
# this leaves you with a `#git commit -m ...` comment in your history
fc # fix command
$VIM => o<esc>V:!git status --porcelain | grep -v ^??
# within vim you're using visual selection with `:!...` to "filter" the selection (a blank line) with an external command
# in the case of `V:!ls` you're filtering the current line through `ls`
# ...which is basically running `ls` (give you a list of files)
# the more complicated `git status --porcelain | grep ...`
# ...lets you "pull in" the output of that command
# ...(with full pipeline support), and then compose
# ...a more complicated (and accurate) command than
# ...messing around on the command line. eg:
git restore --staged FILE1.txt FILE2.txt && git commit -m "...etc..."
Usually you use something like `:!make` to execute the `make` command from vim, but this is an "abuse" of visually-selecting something to filter and replacing the selection with the output. The selection is passed on stdin to the executed command, eg: `V:!tr [a-z] [A-Z]` would be a terribly inefficient way to filter the current line through "tr / uppercase". `ls` as far as I know doesn't really do anything with stdin, so you're basically filtering/replacing the visual selection with the output of `ls` (or any other command), which is great to give you access to accurate filenames or whatever info you can get from a command (`curl`, `git`, `ls`, `apt search ...`, `pip list`, ...etc...).I find using `fc` with `EDITOR=vim` far superior to having the command line (readline) set to "vim/vi" mode, as with `fc`, I'm able to context-switch far easier and have a whole document as a palette / canvas to be able to compose complicated commands.
TL-DR: use <esc .> (escape followed by a period) to access "just the last token/word", and use `# commented-out-command.sh` along with `fc` to have full editing power to accurately compose (or fix) a complicated command.