What are the best, 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!
Since I'm working in git repos the majority of the time, I type these hundreds of times per day:
alias s="git status"
alias d="git diff"
I prefer looking at this stuff in a terminal rather than an IDE. Reducing them to a single character just feels so good. Note: not a git alias like "git s", literally just the single character "s" in Bash itself.
> autocd If set, a command name that is the name of a directory is executed as if it were the argument to the cd command. This option is only used by interactive shells
side note: i started to get into zsh and then serverless. zsh was balking at finding node.js/yarn stuff and running commands. I had to revert back to bash
One/two char git aliases took me to the next level:
alias ci='git commit'
alias co='git checkout'
alias d='git diff'
alias dc='git diff --cached'
alias l='git log --oneline --graph --all --decorate'
alias ru='git remote update'
alias s='git status'
I have one that takes an optional numeric arg for the number of times to repeat. Surprisingly useful, but I still keep meaning to get round to making a nicer interactive one with fzf or something.
$ alias ..
..=up
$ type -f up
up () {
local tmp_path=''
for i in $(seq 1 ${1:-1})
do
tmp_path+='../'
done
cd "$tmp_path"
}
alias search='set -f;search';search() { find . ${2:+-name "$2"} -type f -print0 | xargs -0 grep --color=auto "$1"; }
Recursively searches the files in the current directory for string matches. You can optionally provide a second glob argument to restrict what files to search. This is basically a dumber version of ack-grep, but I wrote it before I learned about ack.
This one I use to find bits in my favourite books/essays, which I have in folders in /books, under e.g. /books/Shakespeare/Macbeth, then search with 'book to be or' etc.
book () {
# Find occurrences of words in texts. Put folders in ~/books, or soft links (ln -s)
# Displays only complete words found, not parts of words.
GREP_COLOR=red
grep -r -n -i --word-regexp --color -C 1 "$*" ./books/
echo `grep -r -i "$*" ./books/ | wc -l` occurrences of \"$*\" found, `grep -i -r --word-regexp "$*" ./books/ | wc -l` as a whole word.
}
'dlm' downloads mp4 file from URL in clipboard
#!/bin/bash
#dlm - download mp4 from clipboard URL. usage: 'dlm myfile' downloads myfile.mp4
#with resume after 5 secs until finish.
fname=$(pbpaste)
echo "Download $fname as $1.mp4 : "
until curl -C - -kLo $1.mp4 "$fname"
do
sleep 5
done
The one I use most often is undoubtedly `g` for `git`. Then I have many aliases inside Git for all kinds of regularly done things, quite a few lifted from Mercurial and then extended; some just shorter names (ci = commit, glog = log --graph) and some more advanced like these three:
fixup = "!f() { TARGET=\"$(git rev-parse \"$1\")\"; shift; git commit --fixup=\"$TARGET\" \"$@\" && git -c core.editor=true rebase --interactive --autostash --autosquash \"$TARGET^\"; }; f"
in = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch..$branch@{upstream}\" \"$@\"; }; f"
out = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch@{upstream}..$branch\" \"$@\"; }; f"
My most recent addition to my shell profile (a couple of weeks ago) enhances ts from the moreutils package. ts provides timestamps (relative to process execution or absolute) at the start of each line of stdout. My enhancement makes it cover stderr as well, so that stdout lines get a green timestamp and stderr lines get a red timestamp. Due to how interlacing works, and the fact that I commonly pair this with concurrency in the form of `make -j8`, it’s not perfect (can end up with a line possessing both green and red timestamps, and then none on the next line), but it’s still really helpful. I just need to get round to adding something to it to make programs still colour their own output. `script` can do that, I think.
(Each ^[ shown there is a literal ␛.) ts-fancy was the temporary name I gave it at first, haven’t renamed it to anything more permanent yet, so it’ll probably stay that way forever.
Usage, `ts-fancy make -j8 --keep-going` and things like that. It’s proving really helpful when figuring out what’s slow in something that verbosely logs, and also in highlighting error output mixed in with normal output.
This exercise made me wish for a smarter terminal that kept track of timestamps and whether output went to stdout or stderr itself (at the character level, even, to resolve the problems of this line-based approach). I shouldn’t have to do this, and you know how often you think after the fact that it’d be nice to have timestamps?
... which shows the previous command exit code, the current time (with second resolution) and the ordinary stuff like username host and working dir, so it looks somewhat like:
I contemplated that for a while a few years back, but decided against it for several reasons:
① I didn’t like an overly-long prompt. On my own machine I already exclude username and hostname, so it’s just `~/Work$ `. (Sometimes PWD gets a bit long, but generally not too much.)
② It was fairly rare that I actually cared about such a timestamp in any way—if I did, it was normally about time taken, and so I could pipe the program through `time` (this was before I discovered `ts` when figuring “someone must have made a program to do this” a couple of weeks ago when preparing to optimise a build process at work), or execute `date; …; date`.
③ Such a timestamp is only written when the prompt is output, rather than when the program is executed (there may be a sane way to have it work otherwise—I didn’t investigate in any way thoroughly—but my initial thoughts suggested any hacky attempt to move the cursor after the fact would interact badly with commands that cause the command line to span multiple lines). This made it useless for well over 90% of the cases when I might have benefited from it (retroactive timing of the duration of a command, rather than at what o’clock I… probably did something).
I return to the desire for a very mildly intelligent terminal that notes when characters were written to screen when not in raw mode, for optional viewing.
I work at a company with micro services so we have a lot of repos. We use nodejs and in some cases use different node versions among different services. Having the prompt show what branch I'm in and what node version I'm on is quite helpful:
PS1="\[\033[01;31m\]Node \`node --version\`: \[\033[01;32m\]\`pwd\` \`git status -sb 2> /dev/null | head -n 1\`\n\[\033[01;34m\]\`date +'%a, %B %-d, %-l:%M:%S%P'\` \[\033[01;31m\]\$ \[\033[00m\]"
Pruning branches both remote and locally are also very helpful to do in these alias/functions:
cdf () {
target=`osascript -e 'tell application "Finder" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)'`
if [ "$target" != "" ]
then
cd "$target"
pwd
else
echo 'No Finder window found' >&2
fi
}
I have a whole repository also including several dotfiles that I maintain for already several years [1].
Following are some snippets from the dotfiles/.alias and dotfiles/.functions files from that repository that probably are the most interesting and which I am using on a regular basis:
# easier navigation
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."
alias ~="cd ~"
# Get current public ip address
alias ip="dig +short myip.opendns.com @resolver1.opendns.com"
# Alias for summing a column
alias mksum="paste -sd+ - | bc"
# Export pbcopy / pbpaste to linux
if [[ "${OSTYPE}" == "linux"* ]]; then
alias pbcopy="xclip -selection clipboard"
alias pbpaste="xclip -selection clipboard -o"
fi
# create a new directory and enter it
function mkd() {
mkdir -p "$@" && cd "$_";
}
# plot stuff directly from the command line.
# Example: seq 100 | sed 's/.*/s(&)/' | bc -l | plot linecolor 2
# -> Generate 100 numbers, wrap it in s(<num>) and calc sin(<num>)
function plot() {
{ echo 'plot "-"' "$@"; cat; } | gnuplot -persist;
}
# wrapper for easy extraction of compressed files
function extract () {
if [ -f $1 ] ; then
case $1 in
*.tar.xz) tar xvJf $1 ;;
*.tar.bz2) tar xvjf $1 ;;
*.tar.gz) tar xvzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar e $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xvf $1 ;;
*.tbz2) tar xvjf $1 ;;
*.tgz) tar xvzf $1 ;;
*.apk) unzip $1 ;;
*.epub) unzip $1 ;;
*.xpi) unzip $1 ;;
*.zip) unzip $1 ;;
*.war) unzip $1 ;;
*.jar) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "don't know how to extract '$1'..." ;;
esac
else
echo "'$1' is not a valid file!"
fi
}
You might enjoy replacing your extract function with atool (https://www.nongnu.org/atool/) which provides aunpack. It works similarly, but has niceties like creating and unpacking into a subdirectory to avoid accidentally spraying files all over the current working directory if the archive has multiple files at its root.
That extract function seems redundant. GNU tar already auto-detects the compression format of the archive, so `tar xvf archive.tar.xz` will work as expected (the J flag is not needed.) bsdtar does the same, and it supports formats other than tar, so `bsdtar xvf archive.zip` works too. These tools use the content of the file rather than the file extension, so they should be more reliable.
How often do you use that and how often do you get it right? :-)
My cd related aliases are the following. Especially the .<number> is surprisingly useful, although most of the time I only use .2 and .3
alias ..='cd ../'
alias .1='cd ../'
alias .2='cd ../../'
alias .3='cd ../../../'
alias .4='cd ../../../../'
alias .5='cd ../../../../../'
# sometimes, the space gets swallowed
alias cd.='cd .'
alias cd..='cd ..'
But that gave me an idea for another useful directory changer: "go to project root".
Project root definition could vary, although nowadays it is probably "go to the first directory upstream with a .git directory"
Used to work primary using docker on my laptop, but been working on some bigger applications that need to be run on beafier machines, so just set environment variable and have these:
$ cat ~/bin/docker
#!/bin/bash
if [ "$DOCKER_HOST" != "" ]
then
HOST_ARG="-H $DOCKER_HOST"
fi
/usr/bin/docker $HOST_ARG $@
$ cat ~/bin/docker-compose
#!/bin/bash
if [ "$DOCKER_HOST" != "" ]
then
HOST_ARG="-H $DOCKER_HOST"
fi
/usr/local/bin/docker-compose $HOST_ARG $@
This one automatically lists the files in the current directory, but limits the number of lines.
function cd {
builtin cd "${@}"
if [[ "$(stat -c "%b" .)" -lt "100" ]]
then
if [ "$( ls -C -w $COLUMNS | wc -l )" -gt 30 ] ; then
ls -C -w $COLUMNS --color=always | awk 'NR < 16 { print }; NR == 16 { print " (... snip ...)" }; { buffer[NR % 14] = $0 } END { for( i = NR + 1; i <= NR+14; i++ ) print buffer[i % 14] }'
else
ls
fi
fi
}
Out of everything I like this little alias the most:
cls="clear; ls"
It harkens back to DOS. Clearing the screen followed by ls happens surprisingly often, if not just to start things in "clean slate". I'm quite fond of it.
287 comments
[ 2.8 ms ] story [ 273 ms ] threadAnd coming in third:
I also have `..`, but also `...` which maps to `cd ../..`
> autocd If set, a command name that is the name of a directory is executed as if it were the argument to the cd command. This option is only used by interactive shells
Making 'cd' more explicit:
Up directory This one I use to find bits in my favourite books/essays, which I have in folders in /books, under e.g. /books/Shakespeare/Macbeth, then search with 'book to be or' etc. 'dlm' downloads mp4 file from URL in clipboardalias ll="ls -l"
alias ..="cd .."
alias ...="cd ../.."
alias mdd='mkdir $(date -I)'
alias cdd='cd $(date -I)'
alias xt="xtermset -T "
alias dtail="dmesg|tail"
It’s currently this shell function:
(Each ^[ shown there is a literal ␛.) ts-fancy was the temporary name I gave it at first, haven’t renamed it to anything more permanent yet, so it’ll probably stay that way forever.Usage, `ts-fancy make -j8 --keep-going` and things like that. It’s proving really helpful when figuring out what’s slow in something that verbosely logs, and also in highlighting error output mixed in with normal output.
This exercise made me wish for a smarter terminal that kept track of timestamps and whether output went to stdout or stderr itself (at the character level, even, to resolve the problems of this line-based approach). I shouldn’t have to do this, and you know how often you think after the fact that it’d be nice to have timestamps?
It really seems very useful to have timestamps for every line of output.
I have tried to approximate this in the past, by setting my bash prompt to be:
... which shows the previous command exit code, the current time (with second resolution) and the ordinary stuff like username host and working dir, so it looks somewhat like:① I didn’t like an overly-long prompt. On my own machine I already exclude username and hostname, so it’s just `~/Work$ `. (Sometimes PWD gets a bit long, but generally not too much.)
② It was fairly rare that I actually cared about such a timestamp in any way—if I did, it was normally about time taken, and so I could pipe the program through `time` (this was before I discovered `ts` when figuring “someone must have made a program to do this” a couple of weeks ago when preparing to optimise a build process at work), or execute `date; …; date`.
③ Such a timestamp is only written when the prompt is output, rather than when the program is executed (there may be a sane way to have it work otherwise—I didn’t investigate in any way thoroughly—but my initial thoughts suggested any hacky attempt to move the cursor after the fact would interact badly with commands that cause the command line to span multiple lines). This made it useless for well over 90% of the cases when I might have benefited from it (retroactive timing of the duration of a command, rather than at what o’clock I… probably did something).
I return to the desire for a very mildly intelligent terminal that notes when characters were written to screen when not in raw mode, for optional viewing.
It just spawns the actual command in a sub process, but may be the output may be more ordered than that of a pipe of ts commands.
[0] https://github.com/spytheman/gostamp
Open current OSX Finder directory in Terminal:
How often do you use that and how often do you get it right? :-)
My cd related aliases are the following. Especially the .<number> is surprisingly useful, although most of the time I only use .2 and .3
But that gave me an idea for another useful directory changer: "go to project root".Project root definition could vary, although nowadays it is probably "go to the first directory upstream with a .git directory"
Edit: found this elsewhere in this discussion posted by jgresty https://news.ycombinator.com/item?id=18901834
https://github.com/jleclanche/dotfiles
https://github.com/paulirish/git-open