What are the most useful aliases or functions etc for bash that you’ve collected or written? Or bash scripts. Please give explanation/usage if necessary. Ones you actually use often. Thanks!
A really useful thing is to always display the error code unless it’s 0. Got used to it real quick and don’t know how I lived without it.
prompt_show_ec () {
# Catch exit code
ec=$?
# Display exit code in red text unless zero
if [ $ec -ne 0 ];then
echo -e "\033[31;1m[$ec]\033[0m"
fi
}
PROMPT_COMMAND="prompt_show_ec; $PROMPT_COMMAND"
### EXIT
### prints last exit code
### but only if non-zero
colored_exit_code() {
echo "%(?..${nl}%F{8}exit %F{1}%?)%f"
}
custom_prompt_exit='$(colored_exit_code)'
boop plays a happy sound if the previous command exited successfully (i.e., exited with status code 0) and a sad sound otherwise. For example, if I’m running a long-running test, I might run npm test ; boop. It helps me know whether something finished, and whether something went wrong.
tempe creates a temporary directory and cds into it.
On a similar note, I have this in my .bash_profile (Mac):
function alert_if_not_in_foreground {
if ! lsappinfo front | xargs lsappinfo info -only name | grep 'Terminal' > /dev/null; then
printf "\a"
fi
}
PS1='$(alert_if_not_in_foreground) ... more stuff ...'
So when I leave some long-lived command running, and by the time it’s finished I’m not looking at the Terminal, it prints the bell character (which on my setup will also make the Terminal.app icon bounce and show a notification badge) so I don’t need to remember to check it periodically.
I guess it could be done with PROMPT_COMMAND as well, which this thread just taught me about :)
vg: Shell function to open grep results directly in Vim using the quickfix. A bit of expounding here, in a small blog post.
rg foo (with ripgrep) to simply view results
vg foo to use the results as a jumping point for editing/exploring in Vim.
A ton of aliases to shorten frequently used commands. Few examples:
When I want to sync a Git repo, I run gf to fetch, glf to review the fetched commits, then gm to merge. git pull if I’m lazy and want to automatically merge without reviewing
glp to review new local commits before pushing with gp. Both glf (“git log for fetch”) and glp (“git log for push”) are convenient because my shell prompt shows me when I’m ahead or behind a remote branch: https://files.emnace.org/Photos/git-prompt.png
tl to list tmux sessions, then ta session to attach to one. I name tmux sessions with different first letters if I can help it, so instead of doing ta org or ta config, I can be as short as ta o and ta c
Also, “aliases” for Git operations that I relegate to Fugitive. Technically these are shell functions, but they exist mostly just to shorten frequently used commands.
Instead of gs for git status, I do vs and open the interactive status screen from Fugitive (which after a recent-ish update a few years ago, is very Magit-like, if you’re more familiar).
When I’m faced with a merge conflict, I do vm to immediately open Vim targeting all the merge conflicts. The quickfix is populated, and I jump across conflicts with [n and ]n thanks to a reduced version of vim-unimpaired.
ez: Probably my favorite one. A script to run FZF, fuzzy-find file names, and open my editor for those files. Robust against whitespaces and other special characters. I also have a short blog post expounding on it.
watchrun: A convenience command to watch paths with inotifywait and run a command for each changed file. For example, watchrun src -- ctags -a to incrementally update a tags file.
notify-exit: Run a command and shoot off a libnotify notification if it finishes (whether with a successful exit code or not). I have it aliased to n for brevity (using a symlink). For example, n yarn build to kick off a long-running build and be notified when it’s done.
Also, a remote counterpart rnotify-exit, which I have aliased to rn (using a symlink). For example, rn ian@hostname yarn build on a remote machine (within my LAN) to kick off a build, and have it still notify on my laptop.
And a slew of scripts that are a bit more integrated with tools I use, e.g.:
rofi-pass-type, rofi-pass-clip, and gen-pass: A set of scripts using Rofi to fuzzy-find passwords in my password manager, Unix pass, and automatically type, copy to clipboard, or generate a new one, respectively.
I used to have a ton of these git shortcuts but at some point I threw them out again because I kept forgetting them. The only thing I use daily is git up which is git pull --rebase.
notify-exit: that’s one of those ideas that is so great you facepalm and ask yourself why you never thought of it before. I’m adding this to my config tomorrow.
Why do you store the timestamp in a file rather than an env var? Maybe relatedly: how does this not break if you do something like sleep 20 &; sleep 15 &? I’d expect them to share $timer_file so the second command overwrites the filename for the former.
(Also, thanks for this and your exit code comment, I have been idly wanting both features in my shell for years.)
PROMPT_COMMAND executes before printing the prompt, so background jobs will not be timed. I wanted to use an env var but had trouble getting it to work, so if you do, please let me know!
# Maintain a merged history across all shells
HISTSIZE=5000
HISTFILESIZE=-1
HISTCONTROL=ignoredups:erasedups
shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
Then remap the up and down arrow keys to search the history using the currently entered command (up to the cursor) as the search term.
I use https://github.com/ellie/atuin to keep a syncable sqlite database of my shell history. Hit Ctrl+R and go through an interactive search. It’s pretty great.
I make k a function which inspects the args and splices in $KUBE_CONTEXT and $KUBE_NAMESPACE in appropriate places, so that I can use .envrc and direnv(1) to work in the appropriate kubernetes context and namespace for a given app.
It creates and drops you into a /tmp dir. These get automatically cleaned up on reboot. The sets directory at setting of the alias. It will always take you back to the same tmp dir for that shell session.
Its pretty basic but prevents a lot of cutter.
I learned that /tmp is not always mounted as tmpfs; on WSL, for instance, this directory persists even after reboot.
To ensure mktemp -d creates an actual temporary directory, one should create and mount a tmpfs themselves (in their home directory, maybe?), and have a $TMPDIR environment variable pointing to this directory, before calling mktemp(1). Seems inefficient, though.
alias g="git"
alias la='ls -lA --color=auto'
alias sc='screen -xRS'
alias sl='screen -list'
# With this function you can explore the filsystem,
# and display contents of both directories and files
# without going to the beginning of the line to
# switch between ls and less.
l() {
if [ -z "$2" -a -f "$1" ] ; then
less "$1"
else
ls -l --color=auto "$@"
fi
}
# Create and enter a directory
function mkcd { mkdir -p "$1"; cd "$1"; }
I happen to use basically the same l and mkcd functions. Tip: I would be tempted to put && between mkdir and cd.
Here is an extended mkcd function that also allows to carry files while changing directory. I use fish, so it’s in fish:
function mkcd --description 'create, move zero or more files into and enter directory'
set -l argc (count $argv)
if test $argc -eq 0
echo "Usage: $_ [carry files…] destdir/"
return
end
mkdir -p $argv[-1]
and if test $argc -gt 1
mv $argv
end
and cd $argv[-1]
end
I’ll use cpwd to copy the $PWD and then change to that directory in >= 1 tmux pane by pasting which works because I have autocd enabled.
I very frequently run git rimraf on the default branch to sync up and delete any local branches that were deleted from the origin.
I mimic zsh’s preexec & precmd helpers in bash to do things like update $DISPLAY to avoid stale values in tmux sessions, my history file, and run z to keep track of directory frecency.
alias -g PG="|grep"
alias -g PL="|less"
# foo PL instead of foo | less
I use them daily since years
pvrun: run any command, but mostly cp/mv/tar, wrapped by pv to view I/O progress
Not exactly shell but still use them daily, in my .tigrc:
# u to fixup selected commit
bind main u !git commit --fixup=%(commit)
# r to rebase to selected commit
bind main r !git rebase -i %(commit)~
# P to push-create a new branch pointing at selected commit
bind main P !sh -c "git push origin %(commit):refs/heads/$(printf 'branch name? ' >&2; read reply; echo $reply) --force"
c for cargo and then a bunch of aliases for subcommands in ~/.cargo/config (x = "clean" and so on)
One git alias that I use quite a lot is cane = commit --amend --no-edit. Then pi = !git push ionut +$(git rev-parse --abbrev-ref HEAD) to push (amended) commits for my current branch (ionut is the remote for my upstream fork).
It is not an alias, but my zsh config does this really nice thing where “if a shell command completes when the terminal is not the foreground window, it sends me an alert that I can click to bring that terminal to the foreground”: https://codearcana.com/posts/2013/06/11/my-zsh-theme.html
I’m kind of surprised this hasn’t been mentioned yet, it’s bee around for some time and certainly is one of the most useful features in my .scrc
# ARCHIVE EXTRACTION
# usage: ex <file>
ex () {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.tar.xz) tar xf $1 ;;
*.tar) tar xf $1 ;;
*.tar.zst) uzstd $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*.deb) ar x $1 ;;
*) echo "'$1' cannot be extracted via ex()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
Another little one I often use which is useful if you are making edits to files and keeping backups of originals:
# swap 2 filenames around, if they exist
# usage: swap <file1> <file2>
swap () {
local TMPFILE=tmp.$$
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}
When I use rg to search a codebase, this gives me three lines of context before and after each match. I don’t keep a ripgrep config file; this is all I need. It’s a great default.
I can always override this by setting -A or -B again in a command:
Setting -A and -B explicitly allows for changing them independently on-the-fly. Passing -A or -B after passing -C resets the opposite-direction context to zero.
git-commit-co-author prompts you to choose a co-author (using fzf) and then runs git commit with Co-authored-by: <coauthor> at the end (see GitHub docs):
# Thanks https://github.com/hpcsc/dotfiles/blob/63f194aa553ef83f9edec76991f2265f7962b00e/link/common/zsh/.functions/fzf-functions/fcm
function git-commit-co-author() {
SELECTED_AUTHORS=$(git shortlog -sne | awk '{$1=""}1' | fzf -m)
MESSAGE="\n\n"
# convert newline-delimited string to array, zsh way: https://stackoverflow.com/a/2930519
AUTHORS=("''${(f)SELECTED_AUTHORS}")
for AUTHOR in $AUTHORS[@]; do
MESSAGE="''${MESSAGE}Co-authored-by: ''${AUTHOR}\n"
done
if [[ "$1" == "-m" ]]; then
git commit -m "$2$(echo -e ''${MESSAGE})"
else
git commit $@ -t <(echo -e ''${MESSAGE})
fi
}
I have aliased it to gcap and run it regularly when pair-programming. It’s not perfect, there are some unhandled edge cases but it works perfectly for me.
commit and amend. I use git heavily, with tons of small commits and history rewriting. These commands show the diff, get y/n answer, and create a new commit/amend the last one, without launching editor for commit message. Very marginal win over just doing that manually.
ip -br doesn’t work and neither does ip -c or ip -br -c.
And now I finally grasped that it would output the same as 'ip' - so it is -brief -color. Sorry, brainfart (ofc I searched before I asked that last question..) :P
Apparently I have never used either flag and didn’t notice them in the manual. – signed, someone gowing up with ifconfig
I was going to post this as my most useful, because I just it all the time.
I also have ...="cd ../.." and so on for going up more levels. Probably not useful beyond four or five levels due to how quickly can you count how deep you are in the CWD.
Edit: Just to be clear, I’m talking about me visually counting up how many levels deep I am in the directory tree. Beyond three or four, I tend to just go up that much, and then look and see where I am and maybe do it again, with my finger hovering over the ‘.’ key. I don’t have a problem rapidly tapping out the ‘.’ nine times to go up 8 levels, the difficulty (for me) is determining that I want to go up 8, vs. 7 or 9 levels.
Even more fun (only works in zsh, as far as I know):
function rationalize-dot {
if [[ $LBUFFER = *... ]]; then
LBUFFER=${LBUFFER[1,-2]}
LBUFFER+=/..
else
LBUFFER+=.
fi
}
zle -N rationalize-dot
bindkey . rationalize-dot
You can make this even better by adding setopt auto_cd to your config, so that if you type a directory path zsh automatically changes to that directory.
Interesting. I’ve never tried to install / use those “smart” cd replacements, where you can type “cd foobar” and it looks at your recent working directories to find a “foobar” and go there.
I was thinking about a variant of your up function that does something like that, where I can type “up foo” in the current directory:
/home/username/foobar/one/two/three/four/
And so it just looks into successive parent directories for anything matching “foo”, and the first one it finds is the destination.
.. for cd ..
sl for ls
gittree for "git log --graph --all --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'"
for displaying a nice git history tree.
# bind ctrl-E to "edit fuzzy"
function edit_fuzzy() {
TARGET=$(fzf)
if [ $? -eq 0 ]
then
echo -e "${PS1@P}edit $TARGET"
history -s "edit $TARGET"
edit "$TARGET"
READLINE_LINE=""
fi
}
bind -x '"\C-e":edit_fuzzy'
Which binds ctrl-E to “select a file, then open it in ‘edit’” (an alias for kwrite). Adjust editor name for taste. The magic is that this also pretends that you typed in “edit filename” manually and pressed return, going so far as to inject that command into your history.
The best answer “for you” here is probably a meta answer. Save all (or a very large portion) of your shell history - not suppressing duplicates - and periodically examine it for useful abstractions/abbreviations.
This can probably be automated, and I’d look for child responses to this post for someone mentioning such tools, but it’s also kind of hard AI-complete to extract good abstractions statistically (and indeed, somewhat subjective in the end, even with personalized statistics). So, while a simple histogram of exact strings is easy and might get you started, the best you can hope for still leaves a lot of manual work (such as separating out the alias/function/script from arguments/context). It is still more precise to your own workflows than trying to crowd source answers here.
The crowd sourcing might get you lots of other nice shell magic ideas, though. :-)
All that said, I can re-re-recommendshowing exit statuses in prompts which I have been doing in Zsh since 1994, re-recommend a “cd ../..” hierarchy (I use one ‘.’ for parent, two for parent-of-parent where the one ‘.’ needs to be a shell function that does a ‘source’ only if it has an argument to source else the cd; Autocd makes “..” by itself largely unneeded), re-recommend what Zsh calls REPORTTIME re-done in Bash elsethread, and add a family of head-tail wrappers that use $LINES (updated upon SIGWINCH by Bash/Zsh) to have tq for “tail quarter”, th for “tail half” and so on using $((LINES/4)) and $((LINES/2)). While there are many more, I’d say these 4 categories might have wide appeal (2 of which are not even aliases/functions/wrappers!)
alias realias='$EDITOR ~/.bash_aliases && source ~/.bash_aliases'
alias refunction='$EDITOR ~/.bash_functions && source ~/.bash_functions'
mkcd() {
mkdir -p "$1" && cd "$1"
}
But my real favorite is the following. I’m a teacher, and I frequently have
to switch from $HOME/Documents/git-repos/schoolname/YYYY/classname-section1/grades to
$HOME/Documents/git-repos/schoolname/YYYY/classname-section2/grades. With this function,
I enter ccd 1 2 and I’m where I need to be. (That FIXME has
been there forever. I make mistakes rarely enough that I haven’t bothered
to fix it.)
ccd() {
case "$#" in
0|1)
builtin cd $1
;;
2)
newdir=${PWD//$1/$2}
# FIXME TODO
# If the user enters two wrong variables, they trigger the first
# branch of this case statement. They should trigger a different
# error message.
case "$newdir" in
$PWD)
printf "ccd: \$PWD is already $PWD\n" >&2
return 1
;;
*)
builtin cd "$newdir"
pwd
;;
esac
;;
*)
printf "ccd: wrong arg count\n" 1>&2
return 1
;;
esac
}
Worth noting things like ‘autopager’, ‘fzr’, ‘t’ (touch, but creates intermediate directories), ‘mcd’, ‘install-manual’, ‘kw’ (opens any program in a new split in kitty, used constantly). Also see my extensive git aliases that make heavy use of fzf. A lot of people are mentioning prompts… I wrote my own in Zig so it’s fast and cross-shell, see kbd/prompt.
Paired with git fetch origin, you see the diff of what changes other people made to the remote copy of the branch, but not polluted with any differences you locally have committed to the branch. i.e. strictly their work, none of your work.
These will only work in zsh but I have a few for iterating over input which are useful in a pipeline:
alias 'each{'='while { read -rA argv } {'
alias 'each'='while { read -rA argv }'
alias 'eachl{'='while { read -r argv } {'
alias 'eachl'='while { read -r argv }'
Another alias where I include the opening brace is this one for enabling xtrace:
alias -- '-x{'='() { setopt localoptions xtrace; '
I also have a few aliases with names starting with +, e.g. for adding the current directory to the path or fpath arrays:
alias -- +fpath='fpath=( ~+ $fpath)'
alias -- +path='path=( ~+ $path)'
For modifying arrays, it is also useful to alias vared with IFS changed to do line-based editing:
alias lvared="IFS=\$'\n\n' vared"
And if you use vi mode, you may prefer:
alias vared='vared -i vi-cmd-mode'
Aliases are also useful for applying noglob and nocorrect for a few commands. git mostly does its own globbing so there’s little need for zsh globbing with it and this avoids a certain amount of quoting. nocorrect is useful with commands like mkdir that take something which won’t exist yet as an argument.
for com in alias expr find git iptables mattrib mcopy mdir mdel unset which;
alias $com="noglob $com"
A zsh odditity is that if an alias ends in a space, it will do alias expansions on the next word too. So this can be applied for commands that precede other commands:
for com in command builtin time nice - nocorrect exec rusage noglob eval nohup;
alias -- $com="$com "
Aside from that, most of my aliases are fairly boring and would work in bash. Here’s just a few of them:
alias apb=ansible-playbook
alias iperl='perl -de1'
alias peminfo='openssl x509 -text -in'
alias toimg='convert -font Inconsolata-Regular label:@-'
alias scat='sed -n l'
alias serve='ruby -run -ehttpd . -p8000'
alias smarties='smartctl -A -f brief'
alias week='date +%V'
alias xkev="xev|sed -ne '/^KeyPress/,/^$/p'"
I have quite a few wrapping curl for sites like wttr.in, rate.sx, ifconfig.me and sprunge.us.
p=python3; cr=cargo run. Various important folders have their names aliased to cd into them.
+=git add. g is an alias to gt, a python script that does more alias expansion. g c=git commit; g am=git commit --amend; g dc=git diff --cached. It also prints a warning if I commit certain monstrosities. But lately I try to favor fugitive.
i3: keybindings for a script to wget/yt-dlp the url in the clipboard, showing a menu for: into a particular directory, with a particular name, using the previous_name+1.
This can be quite a dangerous thing to do. It was really popular where I used to work and I know of more than one instance where someone was so used to it being there that they accidentally removed a load of files when using a different login. If you want such an alias call it something else like ri.
# Submit command but keep command & cursor at same position
bindkey '^\n' accept-and-hold
stty -ixon # Disable XON/XOFF output control (^S/^Q)
bindkey '^R' history-incremental-pattern-search-backward
bindkey '^S' history-incremental-pattern-search-forward
# No longer need to quote URLs with yt-dlp (youtube-dl)
alias ytdl='noglob yt-dlp'
I have a fzf setup in fish that started out as a function, and then moved into a plugin: https://github.com/mk12/fish-fzf. It mostly works with a single shortcut that aims to “do what I mean”.
Ctrl-O: fzf files
Already started typing a path? Start from there.
Extra stuff at end of that path? Start with that query.
Has keybindings to switch files/directories, navigate up/down directories, show hidden files, etc.
Previews files with bat and directories with exa, or falls back to cat and ls.
After selection:
Command line not empty, or more than 1 selected? Insert on command line.
A really useful thing is to always display the error code unless it’s 0. Got used to it real quick and don’t know how I lived without it.
Good point! I also have a prompt function for it, in zsh (screenshot: https://files.emnace.org/Photos/prompt-exit.png):
Indispensable for prototyping and shell scripting.
I also like some of the oh my zsh themes and the like that will color code this for you as well.
A couple small ones I’ve made:
boop
plays a happy sound if the previous command exited successfully (i.e., exited with status code 0) and a sad sound otherwise. For example, if I’m running a long-running test, I might runnpm test ; boop
. It helps me know whether something finished, and whether something went wrong.tempe
creates a temporary directory andcd
s into it.I use these many times per day.
On a similar note, I have this in my .bash_profile (Mac):
So when I leave some long-lived command running, and by the time it’s finished I’m not looking at the Terminal, it prints the bell character (which on my setup will also make the Terminal.app icon bounce and show a notification badge) so I don’t need to remember to check it periodically.
I guess it could be done with PROMPT_COMMAND as well, which this thread just taught me about :)
Looks like a good idea. Where does that
sfx
command comes from though?Right here. It’s basically just a wrapper around mpv.
Which sound files are you using?
These two.
Oh, I have quite a few!
For shell aliases and functions:
vg: Shell function to open grep results directly in Vim using the quickfix. A bit of expounding here, in a small blog post.
rg foo
(with ripgrep) to simply view resultsvg foo
to use the results as a jumping point for editing/exploring in Vim.A ton of aliases to shorten frequently used commands. Few examples:
gf
to fetch,glf
to review the fetched commits, thengm
to merge.git pull
if I’m lazy and want to automatically merge without reviewingglp
to review new local commits before pushing withgp
. Bothglf
(“git log for fetch”) andglp
(“git log for push”) are convenient because my shell prompt shows me when I’m ahead or behind a remote branch: https://files.emnace.org/Photos/git-prompt.pngtl
to list tmux sessions, thenta session
to attach to one. I name tmux sessions with different first letters if I can help it, so instead of doingta org
orta config
, I can be as short asta o
andta c
Also, “aliases” for Git operations that I relegate to Fugitive. Technically these are shell functions, but they exist mostly just to shorten frequently used commands.
gs
for git status, I dovs
and open the interactive status screen from Fugitive (which after a recent-ish update a few years ago, is very Magit-like, if you’re more familiar).vm
to immediately open Vim targeting all the merge conflicts. The quickfix is populated, and I jump across conflicts with [n and ]n thanks to a reduced version of vim-unimpaired.For scripts:
First off, an easy way to manage my PATH scripts:
binify
my scripts so they go into PATH,binedit
if I need to make a quick edit.ez: Probably my favorite one. A script to run FZF, fuzzy-find file names, and open my editor for those files. Robust against whitespaces and other special characters. I also have a short blog post expounding on it.
watchrun: A convenience command to watch paths with inotifywait and run a command for each changed file. For example,
watchrun src -- ctags -a
to incrementally update a tags file.notify-exit: Run a command and shoot off a libnotify notification if it finishes (whether with a successful exit code or not). I have it aliased to
n
for brevity (using a symlink). For example,n yarn build
to kick off a long-running build and be notified when it’s done.rn
(using a symlink). For example,rn ian@hostname yarn build
on a remote machine (within my LAN) to kick off a build, and have it still notify on my laptop.And a slew of scripts that are a bit more integrated with tools I use, e.g.:
I normally keep these in fixed locations, so everything I’ve accrued naturally over the years should be here:
I used to have a ton of these git shortcuts but at some point I threw them out again because I kept forgetting them. The only thing I use daily is
git up
which isgit pull --rebase
.I had a similar problem and only kept
branch-history
which showed me the one line commit diff between my feature branch and dev.notify-exit
: that’s one of those ideas that is so great you facepalm and ask yourself why you never thought of it before. I’m adding this to my config tomorrow.ez
, is great, thanks for sharing!After every command that takes more than 10 s, I display the elapsed and finish times. This requires bash 4.4 or later.
Why do you store the timestamp in a file rather than an env var? Maybe relatedly: how does this not break if you do something like
sleep 20 &; sleep 15 &
? I’d expect them to share$timer_file
so the second command overwrites the filename for the former.(Also, thanks for this and your exit code comment, I have been idly wanting both features in my shell for years.)
PROMPT_COMMAND executes before printing the prompt, so background jobs will not be timed. I wanted to use an env var but had trouble getting it to work, so if you do, please let me know!
The ability to recall commands from the history, quickly.
First, keep a large and deduplicated history that is shared across all open terminals in real time.
https://github.com/dkozel/dotfiles/blob/master/home/.bashrc#L17-L22
Then remap the up and down arrow keys to search the history using the currently entered command (up to the cursor) as the search term.
https://github.com/dkozel/dotfiles/blob/master/home/.inputrc
Nothing else comes even half as close in terms of utility.
I use https://github.com/ellie/atuin to keep a syncable sqlite database of my shell history. Hit
Ctrl+R
and go through an interactive search. It’s pretty great.aww yay, glad to hear you like it! :D
This is really useful thanks for sharing
k for kubectl
I make
k
a function which inspects the args and splices in$KUBE_CONTEXT
and$KUBE_NAMESPACE
in appropriate places, so that I can use.envrc
and direnv(1) to work in the appropriate kubernetes context and namespace for a given app.God yes. When people see I have that they chuckle, and then after maybe 10 minutes of working in k8s with them, they immediately make the alias too.
The one that probably gets the most use is
It creates and drops you into a
/tmp
dir. These get automatically cleaned up on reboot. The sets directory at setting of the alias. It will always take you back to the same tmp dir for that shell session. Its pretty basic but prevents a lot of cutter.I learned that
/tmp
is not always mounted astmpfs
; on WSL, for instance, this directory persists even after reboot.To ensure
mktemp -d
creates an actual temporary directory, one should create and mount atmpfs
themselves (in their home directory, maybe?), and have a$TMPDIR
environment variable pointing to this directory, before callingmktemp(1)
. Seems inefficient, though.Opening JIRA tickets at work (replace
DEV
with your prefix):(simple? yes. Took me forever to consider even doing? yes. HUGE timesaver in meetings where people just rattle off ticket numbers? god yes.)
Up command (copied from stackoverflow) – Takes optional number of levels to
cd ../
:Have done similar thing, will attest to its utility.
Doing this with DNS search domains company-wide is also a good idea: typing
http://jira/1234
should redirect you to the correct ticket.Aliases I always add:
https://lobste.rs/s/qgqssl/what_are_most_useful_aliases_your_bashrc#c_fqu7jd
For vi addicts:
ah! I came to post the second one :)
extra niceties with git
ga
->git add
gap
->git add -p
gb
->git branch
gc
->git checkout
gp
->git push
gbb
->git for-each-ref --sort=committerdate refs/heads/ --format=%(committerdate) %(refname:short)
(last one prints your branches sorted by last commit date, great for finding the “recent branches”
I have sl aliased to ls to catch typos lol
If you install the
sl
package, you get a steam locomotive blocking your terminal for a few seconds.I happen to use basically the same
l
andmkcd
functions. Tip: I would be tempted to put&&
between mkdir and cd.Here is an extended mkcd function that also allows to carry files while changing directory. I use fish, so it’s in fish:
cpwd
to copy the$PWD
and then change to that directory in >= 1 tmux pane by pasting which works because I haveautocd
enabled.git rimraf
on the default branch to sync up and delete any local branches that were deleted from the origin.$DISPLAY
to avoid stale values in tmux sessions, my history file, and runz
to keep track of directory frecency.weather
.A
PROMPT_COMMAND
:Most other things I want to remember are in my
.bash_history
.zsh only:
I use them daily since years
pvrun: run any command, but mostly cp/mv/tar, wrapped by pv to view I/O progress
Not exactly shell but still use them daily, in my
.tigrc
:c
forcargo
and then a bunch of aliases for subcommands in~/.cargo/config
(x = "clean"
and so on)One
git
alias that I use quite a lot iscane = commit --amend --no-edit
. Thenpi = !git push ionut +$(git rev-parse --abbrev-ref HEAD)
to push (amended) commits for my current branch (ionut
is the remote for my upstream fork).It is not an alias, but my zsh config does this really nice thing where “if a shell command completes when the terminal is not the foreground window, it sends me an alert that I can click to bring that terminal to the foreground”: https://codearcana.com/posts/2013/06/11/my-zsh-theme.html
https://github.com/awreece/prezto/blob/76c70b21d8f6d1f3e5f731fa4040e1a2ff49b702/modules/notify/functions/notify_last_command#L25
It also does a lot of the other nice things, e.g. coloring prompt based on success/failure and showing execution time of last run command.
An alias I use often is mcd which just does mkdir && cd something. I have it since my DOS days I think.
I’m kind of surprised this hasn’t been mentioned yet, it’s bee around for some time and certainly is one of the most useful features in my
.scrc
Another little one I often use which is useful if you are making edits to files and keeping backups of originals:
When I use
rg
to search a codebase, this gives me three lines of context before and after each match. I don’t keep a ripgrep config file; this is all I need. It’s a great default.I can always override this by setting
-A
or-B
again in a command:Couldn’t you do
rg-C 5
?Setting
-A
and-B
explicitly allows for changing them independently on-the-fly. Passing-A
or-B
after passing-C
resets the opposite-direction context to zero.Yeah, I could. Good suggestion.
(replace
vi
with whatever you want)Hah! I did similar with
vizsh
andsrczsh
(and accompanyingvizshe
/srczshe
for the.zshenv
file)Related, I use this snippet every now and again to see what commands I am using a lot to see if I can generate aliases for them.
history | cut -f 7- -d " " | sort | uniq -c | sort | tail -20
I have an alias to search the shell’s command history using fzf (on ksh) then copy it to the clipboard
git-commit-co-author
prompts you to choose a co-author (using fzf) and then runsgit commit
withCo-authored-by: <coauthor>
at the end (see GitHub docs):I have aliased it to
gcap
and run it regularly when pair-programming. It’s not perfect, there are some unhandled edge cases but it works perfectly for me.n 5 cargo test
runs command (cargo test
) five times. Super useful for benchmarking or fighting flaky tests, https://github.com/matklad/config/blob/master/tool/src/n.rs.t
is like /usr/bin/time, but has human-readable output by defaulthttps://github.com/matklad/t-cmd
commit
andamend
. I use git heavily, with tons of small commits and history rewriting. These commands show the diff, get y/n answer, and create a new commit/amend the last one, without launching editor for commit message. Very marginal win over just doing that manually.Not super interesting I reckon. But the ones I use the most.
I don’t really have a lot of super useful aliases. Most of the time is spent making git config aliases and vim stuff.
Is that BSD or a mac? My
ip
doesn’t know either flag.That is
iproute2
. The goal is to have ip be brief by default because I simply do not care about all the information.Thanks, but that’s why I was asking:
ip -br
doesn’t work and neither doesip -c
orip -br -c
.And now I finally grasped that it would output the same as
'ip'
- so it is-brief -color
. Sorry, brainfart (ofc I searched before I asked that last question..) :PApparently I have never used either flag and didn’t notice them in the manual. – signed, someone gowing up with ifconfig
Yeah I found the documentation for these commands a bit lacking when I started utilizing them initially.
I was going to post this as my most useful, because I just it all the time.
I also have
...="cd ../.."
and so on for going up more levels. Probably not useful beyond four or five levels due to how quickly can you count how deep you are in the CWD.Edit: Just to be clear, I’m talking about me visually counting up how many levels deep I am in the directory tree. Beyond three or four, I tend to just go up that much, and then look and see where I am and maybe do it again, with my finger hovering over the ‘.’ key. I don’t have a problem rapidly tapping out the ‘.’ nine times to go up 8 levels, the difficulty (for me) is determining that I want to go up 8, vs. 7 or 9 levels.
Don’t want to keep posting it so I’ll link to the reply i made to the parent:
https://lobste.rs/s/qgqssl/what_are_most_useful_aliases_your_bashrc#c_fqu7jd
You might like to use it too!
You (and others) might be interested in the one from my post to this:
Allows you to just do
up 4
to getcd ../../../..
LIFE-saver.
Even more fun (only works in zsh, as far as I know):
You can make this even better by adding
setopt auto_cd
to your config, so that if you type a directory path zsh automatically changes to that directory.I tend to use https://github.com/wting/autojump for smart CDing, personally!
Interesting. I’ve never tried to install / use those “smart” cd replacements, where you can type “cd foobar” and it looks at your recent working directories to find a “foobar” and go there.
I was thinking about a variant of your
up
function that does something like that, where I can type “up foo” in the current directory:And so it just looks into successive parent directories for anything matching “foo”, and the first one it finds is the destination.
oh man – just use Autojump https://github.com/wting/autojump. I use it on every machine i own and it’s a GODSEND.
That was what I was talking about. I’ll have to give it or maybe zoxide a try and see if I stick with it.
.. for
cd ..
sl for
ls
gittree for
"git log --graph --all --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'"
for displaying a nice git history tree.https://lobste.rs/s/qgqssl/what_are_most_useful_aliases_your_bashrc#c_fqu7jd
Magic on top of Fuzzy Finder:
Which binds ctrl-E to “select a file, then open it in ‘edit’” (an alias for kwrite). Adjust editor name for taste. The magic is that this also pretends that you typed in “edit filename” manually and pressed return, going so far as to inject that command into your history.
The best answer “for you” here is probably a meta answer. Save all (or a very large portion) of your shell history - not suppressing duplicates - and periodically examine it for useful abstractions/abbreviations.
This can probably be automated, and I’d look for child responses to this post for someone mentioning such tools, but it’s also kind of hard AI-complete to extract good abstractions statistically (and indeed, somewhat subjective in the end, even with personalized statistics). So, while a simple histogram of exact strings is easy and might get you started, the best you can hope for still leaves a lot of manual work (such as separating out the alias/function/script from arguments/context). It is still more precise to your own workflows than trying to crowd source answers here.
The crowd sourcing might get you lots of other nice shell magic ideas, though. :-)
All that said, I can re-re-recommend showing exit statuses in prompts which I have been doing in Zsh since 1994, re-recommend a “cd ../..” hierarchy (I use one ‘.’ for parent, two for parent-of-parent where the one ‘.’ needs to be a shell function that does a ‘source’ only if it has an argument to source else the cd;
Autocd
makes “..” by itself largely unneeded), re-recommend what Zsh callsREPORTTIME
re-done in Bash elsethread, and add a family of head-tail wrappers that use$LINES
(updated uponSIGWINCH
by Bash/Zsh) to havetq
for “tail quarter”,th
for “tail half” and so on using $((LINES/4)) and $((LINES/2)). While there are many more, I’d say these 4 categories might have wide appeal (2 of which are not even aliases/functions/wrappers!)There aren’t a lot of game changers, but this alternative to
ps aux | grep
is what I use all the time:colorize
is also quite handy:I have them all on github, although they should be documented: https://github.com/winks/dotfiles/blob/master/zsh/functions.zsh
I use these three a lot.
But my real favorite is the following. I’m a teacher, and I frequently have to switch from
$HOME/Documents/git-repos/schoolname/YYYY/classname-section1/grades
to$HOME/Documents/git-repos/schoolname/YYYY/classname-section2/grades
. With this function, I enterccd 1 2
and I’m where I need to be. (That FIXME has been there forever. I make mistakes rarely enough that I haven’t bothered to fix it.)I have several hundreds. Some I use all the time:
I wish I had time to participate more in the thread, but my entire system setup is in my repo: https://github.com/kbd/setup
Here’s my bin dir: https://github.com/kbd/setup/tree/master/HOME/bin
My aliases: https://github.com/kbd/setup/blob/master/HOME/bin/shell/aliases.sh
Worth noting things like ‘autopager’, ‘fzr’, ‘t’ (touch, but creates intermediate directories), ‘mcd’, ‘install-manual’, ‘kw’ (opens any program in a new split in kitty, used constantly). Also see my extensive git aliases that make heavy use of fzf. A lot of people are mentioning prompts… I wrote my own in Zig so it’s fast and cross-shell, see kbd/prompt.
alias gitdo='gitdiff ...@{u}'
Paired with
git fetch origin
, you see the diff of what changes other people made to the remote copy of the branch, but not polluted with any differences you locally have committed to the branch. i.e. strictly their work, none of your work.These will only work in zsh but I have a few for iterating over input which are useful in a pipeline:
Another alias where I include the opening brace is this one for enabling xtrace:
I also have a few aliases with names starting with
+
, e.g. for adding the current directory to the path or fpath arrays:For modifying arrays, it is also useful to alias
vared
withIFS
changed to do line-based editing:And if you use vi mode, you may prefer:
Aliases are also useful for applying
noglob
andnocorrect
for a few commands.git
mostly does its own globbing so there’s little need for zsh globbing with it and this avoids a certain amount of quoting.nocorrect
is useful with commands likemkdir
that take something which won’t exist yet as an argument.A zsh odditity is that if an alias ends in a space, it will do alias expansions on the next word too. So this can be applied for commands that precede other commands:
Aside from that, most of my aliases are fairly boring and would work in bash. Here’s just a few of them:
I have quite a few wrapping curl for sites like wttr.in, rate.sx, ifconfig.me and sprunge.us.
Classics:
l=ls; c=cd; s=cd ..
Typos:
sl=ls; f=fg; fgfg=fg; gf=fg
p=python3; cr=cargo run
. Various important folders have their names aliased to cd into them.+=git add
.g
is an alias togt
, a python script that does more alias expansion.g c=git commit; g am=git commit --amend; g dc=git diff --cached
. It also prints a warning if I commit certain monstrosities. But lately I try to favor fugitive.i3: keybindings for a script to wget/yt-dlp the url in the clipboard, showing a menu for: into a particular directory, with a particular name, using the previous_name+1.
Prompt when
rm
-ingCreate a temporary directory an
cd
into it, very useful when experimenting on a clean slateSimple paste bin, I can use it on a regular file
or pipe into it
Color my
diff
sAlso
ouputs a fish style pwd
~/s/mkws.sh
, I use it in myPS1
.I have a
~/bin/precommit
script that uses my linters https://adi.onl/linters.html. I use it as a generic linter.I store my system wide configs in $HOME in a mirror directory structure of the
/
directory:I use
To actually edit my
/var/cron/tabs/adi
file and install it system wide transparently.My dotfiles https://adi.onl/.*.html.
This can be quite a dangerous thing to do. It was really popular where I used to work and I know of more than one instance where someone was so used to it being there that they accidentally removed a load of files when using a different login. If you want such an alias call it something else like
ri
.Thanks for the warning! Not a bad idea!
Some
zshzle(1)
andzshmisc(1)
goodness.cdg
=> cd up the filesystem until you find the directory that contains a.git
dir.This one’s actually an eshell function:
or in pure shell:
cd "$(git rev-parse --show-toplevel)"
I have a fzf setup in fish that started out as a function, and then moved into a plugin: https://github.com/mk12/fish-fzf. It mostly works with a single shortcut that aims to “do what I mean”.
bat
and directories withexa
, or falls back tocat
andls
.$EDITOR
.cd
to it.alias cls="clear && ls"
is the first thing I set up in any new environment.[Comment removed by author]
vi mapped to vim :)
Mine have to be these:
My very first alias was same as your first one here.. I just made a few more also
Up to four or five dots (sorry, on a phone here, it’s a pain to type it out). Works really well.
Whenever I set up a new laptop it’s always the first thing I add
I like fixssh:
Bash has
$SRANDOM
for a 32-bit cryptographically secure random number. ZSH however doesn’t. So I wrote a simple function:In action: