Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Best things in your bash_profile/aliases?
345 points by yesenadam on Jan 13, 2019 | hide | past | favorite | 277 comments
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!

My favorite new one that I have been using a lot:

  function cheat() {
      curl cht.sh/$1
It queries the cht.sh cheatsheet of various Unix commands. 'cheat tar' prints:

  # To extract an uncompressed archive:
  tar -xvf /path/to/foo.tar
  # To create an uncompressed archive:
  tar -cvf /path/to/foo.tar /path/to/foo/
  # To extract a .gz archive:
  tar -xzvf /path/to/foo.tgz
  # To create a .gz archive:
  tar -czvf /path/to/foo.tgz /path/to/foo/
  # To list the content of an .gz archive:
  tar -ztvf /path/to/foo.tgz
  # To extract a .bz2 archive:
  tar -xjvf /path/to/foo.tgz
  # To create a .bz2 archive:
  tar -cjvf /path/to/foo.tgz /path/to/foo/
  # To extract a .tar in specified Directory:
  tar -xvf /path/to/foo.tar -C /path/to/destination/
  # To list the content of an .bz2 archive:
  tar -jtvf /path/to/foo.tgz
  # To create a .gz archive and exclude all jpg,gif,... from the tgz
  tar czvf /path/to/foo.tgz --exclude=\*.{jpg,gif,png,wmv,flv,tar.gz,zip} /path/to/foo/
  # To use parallel (multi-threaded) implementation of compression algorithms:
  tar -z ... -> tar -Ipigz ...
  tar -j ... -> tar -Ipbzip2 ...
  tar -J ... -> tar -Ipixz ...
You do have to be online, but there are ways of downloading the directory of cheat sheets to use offline as well.

This is awesome, I ALWAYS have to google for how to untar an archive (I don't do it often enough to commit to memory) thank you!

I have:

    function extract () {
      if [ -f $1 ] ; then
        case $1 in
          *.tar.bz2)   tar xjf $1     ;;
          *.tar.gz)    tar xzf $1     ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       unrar e $1     ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xf $1      ;;
          *.tbz2)      tar xjf $1     ;;
          *.tgz)       tar xzf $1     ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)     echo "'$1' cannot be extracted via extract()" ;;
           echo "'$1' is not a valid file"

tar czvf

"create ze vucking file"

tar xzvf

"extract ze vucking files"

There are man pages though, but still I suppose that might be useful to you.

Anyways, the only options for tar that I commonly use are "c", "x", and "t"; I will use other programs for decompression, and for extracting into a directory, will use cd.

If the man pages had useful examples the “cheat sheets” would not be needed. So “duh use man pages” is a wrong and annoying answer in this context.

Yes, I suppose you are right, the man pages do not have sufficient examples. So, it is good that they add more there. (The man page still explains what all of the options are; now we have this "cheat sheets" with the examples, too.)

I have an alias "x" setup to run:

      atool --extract $*
That will unpack "anything", into a sub-directory if necessary. Something I use more than any other alias.

There is a similar cli tool called tldr[1]. It's very useful and simple to invoke.

[1] https://github.com/tldr-pages/tldr

Nice. You might consider adding a check for the existence of a local cache file. If it doesn't exist, then try online. i.e.

   if [ ! -s "${cache_dir}"/"$1" ] ; then ...

Thank you. It is so convenient to write some functions is .bash_profile. So powerful new skill.

Cool, but on my Mac it makes flashing text..arggh.

Add -s to curl, should fix it.

s for silent? I mean, all the text on the page is flashing on and off in sync..the whole page goes black. Its the first ESC code in the downloaded text, I guess..haven't quite figured out how to block that yet. If I then do an 'ls' (100s of files in that dir) it stops flashing, but when I scroll up, the first ls-ed files stay flashing..

This is tiny, but I've gotten a surprising amount of mileage out of aliasing 'fx' to

  firefox --new-instance --profile $(mktemp -d)
which pops open a new instance of Firefox with a completely clean, temporary profile.

Super useful for testing sites or add-ons without influencing (or being influenced by) by my normal browsing profile.

I can't believe i never thought of using command line switches for that kind of stuff, i always just have firefox set to forget all data on close.

Not exactly a bash alias, but might be useful too: Since I often get bug reports for specific versions of firefox, i've set up a small script for downloading and starting a given firefox version: https://pastebin.com/t2PHxJqE

What would the Google Chrome equivalent look like?

chromium --user-data-dir $(mktemp -d)

Aye, learnt this when I wanted selenium profiles with some Dev plugins available but not my main profile.

I have a similar command, except it keeps the existing addons from my main profile. Which is useful as I need a proxy for different environments for work.

Please share how you did do that, that sounds awesome!

    PROFILEDIR=`mktemp -p /tmp -d tmp-fx-profile.XXXXXX.d`
    mkdir -p $PROFILEDIR/extensions 
    cd ~/.mozilla/firefox/yvwc47i0.default/
    cp extensions/* $PROFILEDIR/extensions/
    cp addons.json extensions.json $PROFILEDIR/
    cp -R browser-extension-data $PROFILEDIR/
    cp cert_override.txt $PROFILEDIR/
    #cp prefs.js $PROFILEDIR/
    echo 'user_pref("devtools.selfxss.count", 10);' > $PROFILEDIR/prefs.js
    cd -
    firefox -profile $PROFILEDIR -no-remote -new-instance
    rm -rf $PROFILEDIR
Created this as a script somewhere in my path. You'd need to change `cd ~/.mozilla/firefox/yvwc47i0.default/` to match what yours is.

Not GP, but you could just do the same except after making the temp dir: copy in `profile/addons.json` and `-r profile/extension*` from your main profile. (There might be other files needed to, not tested.)

This is great, thanks.

Something funny:

  alias crontab='fuck you, <insert name of colleague here>'

Everyone knows that in a [in]sane workplace, you ALWAYS have to lock your machine. So this particular new hire forgot to lock her machine and one of the seniors (senior prankster, I would say) jumped into her terminal and set a crontab to run EVERY MINUTE.

So she comes back (we pair program so they were actually pairing that day) and goes on with programming for a few seconds. Then she tells us to be quiet. We're all like "WTF?" She asks, "Do you hear some robotic voice saying something?"

At this point we're all trying to listen but to no avail. She thinks it's her machine (which was connected to a 27" monitor) and proceeds to max the volume. A few seconds later, the whole office hears a thundering robotic voice say "ASSHOLE".

Everyone laughs. From that point onwards, we all had shortcuts to lock our screens, and as an added "security" feature, we aliased our crontab to actually say "fuck you" to our senior prankster.

Most of my colleagues used zsh and oh-my-zsh, and as far as I can remember, oh-my-zsh has a mechanism to check for updates every 14 days.

I would then set their .zshrc or whatever to end with

    echo "sleep 0.1" >> ~/.zshrc
so that every time they opened as hell, it would take 100ms longer to run. It would usually take them up to 1-2 second of startup time to figure out what was wrong.

Now my favourite part was that I edited the oh-my-zsh update script to actually echo the original echo line into their ~/.zshrc file, so that even if they figured out what was happening and were very vigilant with locking their laptop, it would happen again within the next 14 days. Loved that.

A colleague did a similar thing, except set it to whisper the time quietly at lengthy but random intervals.

It took the victim so long to figure out what was causing it, that it made it so much funnier.

should be:

say 'fuck you, <insert name of colleague here>'

For Python programmers, I have a bash/zsh function called `pycd` that takes any Python package/module name as an argument, and changes your current working directory to be the library or site-packages location of that library, according to the current python interpreter in your $PATH. Here it is:

    pycd () {
        pushd `python -c "import os.path, $1; print(os.path.dirname($1.__file__))"`;
Example usage, with abbreviated $PWD shown after "»" and shell commands entered after "$" in this example session:

    » (~/repos/web)
    $ pycd flask
    » (~/./v/3/e/w/l/p/s/flask)
    $ pwd
    » (~/./v/3/e/w/l/p/s/flask)
    $ head app.py                                            
    # -*- coding: utf-8 -*-
        This module implements the central WSGI application object.
        :copyright: © 2010 by the Pallets team.
        :license: BSD, see LICENSE for more details.
    » (~/./v/3/e/w/l/p/s/flask)
    $ popd      
    ~/repos/web ~
    » (~/repos/web)
So, usually lets you explore the source code, at the command-line, for any Python libraries you have installed.

Can I add something from .vimrc?

If you put the commands:

  set undofile
  set undodir=~/.vim/undodir
You get infinite undo in your files.

Now when you go into a file, delete or add some text and close your terminal down, the next time you enter vim you can (re|un)do previous operations.

Has saved my ass more times than I care to mention over my career!

You can also delete old (older than 90 days) undo files with the following in your .vimrc:

  let s:undos = split(globpath(&undodir, '*'), "\n")
  call filter(s:undos, 'getftime(v:val) < localtime() - (60 * 60 * 24 * 90)')
  call map(s:undos, 'delete(v:val)')

I can't believe I didn't know about this! Thanks so much :)

I don't want to sound hyperbolic but its kind of a game changer for text editing.

I understand why developers don't have it on by default in other text editors (space) but seeing as I don't fill my HDD with movies or games or any other large media like that, i've got all the space in the world.

I actually wrote 'game changer' in my original comment, and got rid of it for the same reason! Now that I've added it to my vimrc, I'm now upping it to 'life-changing'

This is awesome! Be sure to mkdir ~/.vim/undodir first as vim won't do it for you (or didn't for me)

Late on this but in case it's useful:

  if !isdirectory($HOME . "/.vim/undodir")
      call mkdir($HOME . "/.vim/undodir", "p")
  set undofile
  set undodir=~/.vim/undodir

Excellent if you also use gundo, which gives a nice visual interface to the undo tree in vim.


This is amazing! Just a note: I had to mkdir the directory in ~/.vim to get it work.

Which version of vim added support for this?

Damn! My work machine is cut off from outside networks and restricted to the versions of packages on their repo. Guess I can't use it. :/

You can try Gentoo prefix to install stuff into your $HOME: https://wiki.gentoo.org/wiki/Project:Prefix

Not strictly an alias, but autojump has been a huge productivity booster for me. Installing it sets up an alias of `j` which guesses the best directory to cd to based on your cd history.

So instead of having to type `cd ~/Projects/someproject` you could just type `j some` and it'll end up there.


There's a static version of this built into bash, btw:

    # allow directory variables
    shopt -s cdable_vars
    # set a directory variable
    export some=~/Projects/someproject
You can then say `cd some` from anywhere and end up in `~/Projects/someproject`.

Shoutout as well to the various `warp` implementations[1,2,3]. Instead of guessing, you set "warp points" so for your example you can do something like:

>cd ~/Projects/someproject

>wd add . some

From then on you can use `wd some` to warp to that dir.

[1]: https://github.com/kigster/warp-dir

[2]: https://github.com/mfaerevaag/wd

[3]: https://github.com/troyxmccall/wd

Oh that's slick! That will be helpful for a few of my similarly named projects that autojump gets wrong sometimes.

Such a timesaver indeed. The other one would be fzf [1]. Together they get rid of the endless cd'ing and cursing on the default Ctrl-R for being rather stupid and useless :) And there are powershell counterparts as well (ZLocation and PsFzf).

[1] https://github.com/junegunn/fzf

I've been using z and it's great: https://github.com/rupa/z

Second using z. I couldn't figure out how to get autojump working on windows linux subsystem but z worked perfect right out of the box.

Thanks a lot! Something like that was one of the tiny tools I wrote back on DOS using Borland Pascal (I named it xcd). I figured something like this existed but I never really investigated. autojump is even included in Debian/Ubuntu, so it is trivial to use. I guess putting aside an hour per month to actively apply/install these little tools would be really useful.

+1. Very useful extension

Here is my lot

  # setting common options
  alias cp='cp -iv'
  alias mv='mv -iv'
  alias rmdir='rmdir -v'
  alias ln='ln -v'
  alias ls='ls --color=auto --human-readable --group-directories-first --classify'
  alias grep='grep --color=auto'

  # shortcuts
  alias e=vim
  alias music=ncmpcpp
  alias g='git status'
  alias gp='git push'

  # show pretty git diff
  alias gitdiff='git difftool -y -x "colordiff -y -W $COLUMNS" | less -R'
  # go to root git directory
  alias cdgit='cd $(git rev-parse --show-toplevel)'
  # view csv files in columns
  alias csv='column -s, -t'
  # activate python venv
  alias v='source ./venv/bin/activate'

  # show weather
  alias weather='curl wttr.in/Manchester'
  # get my calendar
  alias c='gcalcli --calendar <redacted> --monday calw'
  # alternate view of calendar
  alias agenda='gcalcli --calendar <redacted> agenda `date --iso-8601`T08 `date --iso-8601`T15'

  # rot13 some text
  alias rot13="tr '[A-Za-z]' '[N-ZA-Mn-za-m]'"

  # I always forget how to echo status code
  alias exitcode='echo $?'

  # make directory and enter it
  mdc() { mkdir -p "$@" && cd "$@"; }
  # create a file and make git track it
  ga() { touch "$@" && git add "$@" }
  # open a twitch stream in mpv
  twitch() { livestreamer --player "mpv -" "http://twitch.tv/$@" best }
  # set terminal window title
  title() { print -Pn "\e]2;$@\a" }
  # open a file with less or a directory with ls
  l() { if [ -f "$1" ]; then less "$1"; else ls "${1:-`pwd`}"; fi }

livestreamer is dead, long live streamlink

I lifted most of this from the guy mentioned in the hn post in the comments below. I don't know what shell/platform he used, but it didn't work from twitter so I tweaked it to work on the linux boxes I typically see.

It creates a different history file from each shell session. Most of my shell history goes back about 3 years now. The downside is you can't up arrow or crtl R except for your current history, but you can use the histgrep function to search everything.

I keep meaning to make another processed file which would uniq the history without the datestamp and maybe hook into fzf, but this has been good enough for now.

  # tricks from https://news.ycombinator.com/item?id=10162189

  if [ ! -d ~/.history/$(date -u +%Y/%m/) ]; then
        mkdir -p ~/.history/$(date -u +%Y/%m/)
  #cat .history/2016/09/* |sort -n| uniq

  export HISTFILE="${HOME}/.history/$(date -u +%Y/%m/%d.%H.  %M.%S)_${HOSTNAME}_$$"
  export HISTSIZE=
  export HISTCONTROL=ignoreboth
  export HISTCONTROL=erasedups
  export HISTTIMEFROMAT="%d/%m/%Y-%H:%M:%S"
  #export PROMPT_COMMAND='history -a'
  export HISTIGNORE='&:bg:fg:clear:ls:pwd:history:exit:make*:* --help:'
  export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
  histgrep () 
  grep -r "$@" ~/.history
  history | grep "$@"

There may be a typo in in this line

export HISTTIMEFROMAT="%d/%m/%Y-%H:%M:%S"


HISTIGNORE is really cool

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.

And coming in third:

    alias ..="cd .."

  alias ..="cd .."
If you use zsh, typing a directory name changes to it automatically. It’s almost always a very delightful thing.

I like

  alias h="cd -"
to go to the last directory I was in. Inspired by how you move the cursor to the left in vim.

Bash has this as well

  set autocd

that would be rather

    shopt -s autocd


> 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

Whoops, sorry. That's right.

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

add z to it!

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 ..
    $ type -f up
    up () {
        local tmp_path=''
        for i in $(seq 1 ${1:-1})
        cd "$tmp_path"

I have the same exact aliases but they check for a Git or SVN repo and then use the right tool accordingly.

I also have `..`, but also `...` which maps to `cd ../..`

I also have '..' and '...', AND '....' heheh. I use that last one a lot

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'

You should try Diff2HTML - https://diff2html.xyz/ install the cli with `npm install -g diff2html-cli`

    alias diff='diff2html -s side'

This lets you easily search your command history by typing the beginning of a command and pressing the up arrow.

    bind '"\e[A": history-search-backward'
    bind '"\e[B": history-search-forward'
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" ]]
        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] }'

The first one is pretty much CTRL+R (reverse incremental search)

Workspace management:

    export WORKSPACE="$HOME/workspace"
    alias ws='cd $WORKSPACE && ls'
History related commands:

    alias h="fc -li 1"  # like `history` but with dates

    # Which commands do I use the most?
    alias histstats="history | awk '{CMD[\$2]++;count++;}END { for (a in CMD)print CMD[a] \" \" CMD[a]/count*100 \"% \" a;}' | grep -v './' | column -c3 -s ' ' -t | sort -nr | nl |  head -n10"

    alias gopath='cd $GOPATH/src && tree -dL 3'

    # --no-pager is underrated
    alias glnp="git --no-pager log --oneline -n30"

    # Have I been pwned?
    # usage: `hibp email@example.com`
    hibp() {
        curl -fsS "https://haveibeenpwned.com/api/v2/breachedaccount/$1" | jq -r 'sort_by(.BreachDate)[] | [.Title,.Domain,.BreachDate,.PwnCount] | @tsv' | column -t -s$'\t'

    # Weather
    alias weather='curl wttr.in/$CITY'

What shell are you using? I'm using bash and don't have the `i` argument in my version of `fc`

I'm using zsh

History with dates is genius! Thanks for sharing it :)

    # ============= #
    # Bash-specific #
    # ============= #
    alias sudo="sudo --preserve-env"
    # Up & down map to history search once a command has been started.
    bind '"\e[A":history-search-backward'
    bind '"\e[B":history-search-forward'
    alias tmux="tmux attach || tmux new"
    alias fuck='sudo "$SHELL" -c "$(history -p !!)"'
    alias fucking="sudo"
    # ========================================================= #
    # GnuPG SSH Authentication                                  #
    # ========================================================= #
    # - Install "gnupg2" and "scdaemon".                        #
    # - Add "enable-ssh-support" to "~/.gnupg/gpg-agent.conf"   #
    #   - Or copy existing config from this repository          #
    # - Find [A]uthentication keygrips "gpg -K --with-keygrip"  #
    # - Add appropriate keygrips to "~/.gnupg/sshcontrol"       #
    # ========================================================= #
    which gpgconf 1>/dev/null 2>&1
    if [ $? -eq 0 ]; then
        export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
        gpgconf --launch gpg-agent

You can use "tmux new -A" instead of two commands

This one is pretty useful!

Open current OSX Finder directory in Terminal:

  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" != "" ]
                cd "$target"
                echo 'No Finder window found' >&2

And `open .` does the opposite: opens Finder to your current directory.

can't you just wite "cd" and drag the folder into the terminal?

Yes, but that's a royal pain. 'cdf' are 3 adjacent keys.

This is the function I use to set PATH:

  function path {
    if [[ -d "$1" ]] ; then
      if [[ -z "$PATH" ]] ; then
        export PATH=$1
        export PATH=$PATH:$1

  export PATH=''

  path ~/.homebrew/sbin
  path ~/.homebrew/bin
  path /usr/local/sbin
  path /usr/local/bin
  path /usr/sbin
  path /usr/bin
  path /sbin
  path /bin
It simplifies the syntax.

I also like to keep vim swaps/backups/history in a centralized place (.vimrc):

  set directory=~/.vim/swaps      " centralized swaps
  set backupdir=~/.vim/backups    " centralized backups
  set undodir=~/.vim/undo         " centralized undo history
I don't like leaving ~clutter in random folders.

I also like to alias sl to ls :)

  alias sl='ls'
Other than that, the least you have to configure the better.

You can check my dotfiles here: https://github.com/krmbzds/dotfiles

A simple but effective one:

  function lie {
    if [[ "$1" == "not" ]]
      unset GIT_AUTHOR_DATE
      return 0
    export GIT_AUTHOR_DATE="$1"
    export export GIT_COMMITTER_DATE="$1"
My employers don't quite need to know how much I procrastinated in that particular task :P

On Linux I use zsh, but these should translate.

Some of my favourite recent ones...

List most recently modified files from the current directory and any below it. Helps remind me what I was working with when I don't ssh into a box regularly :

  alias changedfiles="find . -type f -print0 | xargs -0 stat --format '%Z :%z %n' | sort -nr | cut -d: -f2- | head -n 20"
[ Need to tweak that sometime for BSD find on MacOSX, but I use it primarily on Linux ]

Before backing up from a Unix-typical filesystem to an ExFAT volume attached by USB, find problematic characters in filenames from the current directory and any below :

  function badnames {
	find . -name '*[?<>\\:*|\"]*'

A big favourite on volumes with deeply nested directory structures. My favourite technique for a quick directory find and switch.

If you use FZF, this will show all directories (not files) from the current directory downwards. You can do an incremental fuzzy search by starting to type, and quickly change to that directory by pressing Enter when the desired one is highlighted.

  function fd() {
	local dir
	dir=$(find ${1:-.} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf +m) && cd "$dir"
Love that one. As 'fd' is right under the fingers on the home row, the directory search and switch can look like magic when used quickly as part of the workflow.

My most used alias would be:

  alias fuck='sudo $(history -p !!)'
It runs the previous command as root.

I like that. I'll borrow it, but I'll rename it to 'damn', as 'fuck' it dedicated to https://github.com/nvbn/thefuck.

See also sudo !!

Didn't see this before I posted, but I have basically the same, but I say please instead of fuck. :)

All of my various git alises. I especially like `goops` which is very useful if you just pushed some code and realised you missed something.


   alias gs="g status"
   alias glff="git pull --ff-only"
   alias glffc="git pull origin \$(current_branch) --ff-only"
   alias glc="git pull origin \$(current_branch)"
   alias gpc="git push origin \$(current_branch)"
   alias gpcfl="git push origin \$(current_branch) --force-with-lease"
   function goops { git add -A "$@" && git commit --amend --no-edit && gpcfl }
   alias gbr="git branch -r"
   alias grm="git branch --merged | grep -v \"\*\" | xargs -n 1 git branch -d"
   function mkb() {
       git fetch && git checkout -b "$1" origin/master
`mkdataenv` is nice for spinning up a quick Jupyter environment for all data analysis needs.


    function mkdataenv() {
        mkvirtualenv --python /usr/local/bin/python3 $1
        workon $1
        mkdir "$1"
        cd $1
        pip install pandas jupyter numpy matplotlib seaborn
        pip freeze > requirements.txt
       jupyter notebook

git aliases is best done with git itself, e.g. my favorite git alias is `git alias`, which lists all my git aliases.

  alias.alias config --global --get-regexp ^alias
I really like blameconflict:

  alias.blameconflict blame -L '/^<<<</,/^>>>>/'

I've never liked git aliases, at least not for things I do frequently.

With Z-Shell git aliases have tab completion which is really nice. My workflow often involves something like

  g fp # git fetch --prune
  g rb origin/master master # rebase
  g co -
A lot of tab and very few keys in general when working with git.

My favorite aliases in this context are

  alias wow=git
  alias such=git
  alias many=git
  alias awesome=git
  alias much=git

Here's a function you can use to generate a strong printable password on the fly:

    function gen_passwd () {
        openssl rand 150 |\
        tr -dc  '[:graph:]' |\
        cut -c 1-${1:-13}
The default password length is 13 characters but you can pass a different length parameter instead.


* generate 150 pseudo-random bytes using openssl's rand

* discard non-printable characters

* cut to desired length

Note that it will only use the ASCII character set, if you prefer a solution that also uses german umlauts (öäüÖÄÜß) or something more exotic like emoji in your passwords you're on your own.

I have similar but I remove some visually ambiguous chars.

  tr -d iIlLOo0

I'm trying to use this in mac shell, but it says `tr: Illegal byte sequence`

Try setting LC_CTYPE:

  env LC_CTYPE=C tr ..

I use bash, but I like the zsh feature where you could type "cd -n" and go back n entires in your "directory stack", so I made my own version as a function. It's probably subtly broken in some way, since it's bash, but it works relatively well for me:

  cd() {
  	# Set the current directory to the 0th history item
  	if [[ $1 == -h ]]; then
  		for i in ${!cd_history[@]}; do
  			echo $i: "${cd_history[$i]}"
  	elif [[ $1 =~ ^-[0-9]+ ]]; then
  		builtin cd "${cd_history[${1//-}]}" || # Remove the argument's dash
  		builtin cd "$@" || return # Bail if cd fails
	# cd_history = ["", $OLDPWD, cd_history[1:]]
  	cd_history=("" "$OLDPWD" "${cd_history[@]:1:${#cd_history[@]}}")
Other than that, I doubt there's much that would be generally useful to anyone.

Funnily enough, I did the exact same thing but for zsh's two-argument cd:

  cd() { if [[ -n "$2" && "$1" != "--" ]]; then builtin cd "${PWD/"$1"/"$2"}"; else builtin cd "$@"; fi; };
It's niche functionality, but super useful when you hit its niche:

  user@machine:/usr/src/linux-kbuild-4.9/scripts/mod$ cd 4.9 4.8
I'll leave combining these two as an exercise for the reader.

This one I use daily without thinking about it - it shares my bash history between screens and sessions on a given machine and extends it (grabbed from some corner of the internet):

    # shares history between tabs with prompt_command

    _bash_history_sync() {
      builtin history -a         #1 appends command to histfile
      HISTFILESIZE=$HISTSIZE     #2 sets max size
      builtin history -c         #3 clears current session history
      builtin history -r         #4 reads the updated histfile and makes that the current history

    history() {                  #5 overrides build in history to sync it before display
      builtin history "$@"

Sometimes I forget the name of git branches I've worked on lately. This displays them with dates, most recent at the bottom:

    git_branch_dates() {
      git for-each-ref --sort=authordate --format '%(authordate:iso) %(align:left,25)%(refname:short)%(end) %(subject)' refs/heads
Because I hate typing:

    # for rails migrations and keeping test updated
    alias migrate="rake db:migrate && RAILS_ENV=test rake db:migrate"
Something I should use more to track things I've done lately - this opens up vim at the end of a file in your home dir called did.txt, appends the date and puts cursor at the last line:

    # didfile setup
    alias did="vim +'normal Go' +'r!date' ~/did.txt"
Because sometimes you want to sudo an alias:

    # trailing space in value expands aliases that come after, see: http://www.linuxcommand.org/lc3_man_pages/aliash.html
    alias sudo='sudo '
And displaying the git branch in the prompt:

    # this gets the git branch to display when I cd into a git repo
    parse_git_branch() {
        git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'

    export PS1="\[\033[36m\]\u\[\033[m\]@\[\033[32m\]\h:\[\033[33;1m\]\w\[\033[m\]\[\033[32m\]\$(parse_git_branch)\[\033[00m\]\$ "
Because I often want to check recent files:

    alias llth='ls -hFlat | head'

> this gets the git branch to display when I cd into a git repo

It's early and I'm lazy... will this always parse the branch upon entering any git directory?

Edit: ugh, nevermind it _is_ early. I know that answer. Thanks for the cool functions.

Hope you find them as useful as I have!

  function remac {
    sudo /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -z
    sudo ifconfig en0 ether $(openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//')
    sudo networksetup -detectnewhardware
    echo $(ifconfig en0 | grep ether)
Explanation: https://jezenthomas.com/free-internet-on-trains/

Also, when I need to share a code snippet I pipe it to this:

  alias ix="curl -F 'f:1=<-' ix.io"
Oh, and perhaps the most important part of my .vimrc: https://github.com/jezen/dotfiles/blob/master/.vimrc#L160

One thing I do is to put this snippet in .bashrc or .profile

  for i in ${HOME}/.bash.d/*.sh
    if [ -r ${i} ] ; then
        . ${i}
And drop some custom scripts in ${HOME}/.bash.d/ like alias.sh, env.sh

(my common .bash.d scripts are saved in a git repository)

Whoa, I know someone who does exactly this. Is this a common pattern?

Unless you're him!

.d is a common Unix include directory pattern. See cron.d, xinetrc.d, conf.d etc. Packages can just add/remove things to the include dir rather than modifying the main config.

I do that in my dotfiles too:

The main include:


The actual dotfiles:


(People usually copy the literate emacs configuration ..)

Annoyingly not built in, pathadd and pathrm to make sure re-sourcing your bashrc doesn't hose your environment.

    pathadd() {
        if [ -d "$1" ] && ! echo "$PATH" | grep -E -q "(^|:)$newelement($|:)" ; then
            if [ "$2" = "after" ] ; then

    pathrm() {
        PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"

This is pretty useful for downloading mp3s of songs from youtube:

   alias getmp3="youtube-dl -x --audio-format mp3 "

   getmp3 https://www.youtube.com/watch?v=<id-of-some-nice-tune>

(You'll need to to `pip install youtube_dl` first and probably have `ffmpeg` installed too)

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.

My muscle memory is to set on CTRL+L, ls. But I like it, and the call back to DOS days :)

ah, I've been using `nyancat -f1`

Not as fancy as other tips here, but I bet this is really time saving in the long run for most developers.

My core work is alway around ~10 directories, which are mostly code packages. As soon as I start working on a project/team, I create aliases for directories. They take the form:

  alias agg="cd /ws/ProjectName/src/PackageName/ &&
             echo -n -e '\033]0;PackageName\007' &&
The first part of course navigates to the directory. The second part sets the tabName of my iTerm to the package name. The last part sets the background color of the tab to something unique for the package. This makes it easy to spot the right tab when I have like 10 iTerm tabs open.

In case you want to see the definition of the last part:

    set_tab_color() {
        echo -ne "\033]6;1;bg;red;brightness;$1\a"
        echo -ne "\033]6;1;bg;green;brightness;$2\a"
        echo -ne "\033]6;1;bg;blue;brightness;$3\a"
    tab-color-devil-blue() { set_tab_color 34 112 147 }
Tested only in iTerm.

In my previous setup, I had a function that displayed a menu when I started bash, listing all my "main" directories. So each time you started a session you just had to press 1-7 to go where you wanted.

That is a great idea. Thank you!

Definitely save me some time and effort. The only issue I had was that sometimes when I wanted to use bash from, like, another app it would start the menu so it wouldn't work to use it from them. I'm sure it can be worked around but it was never a real issue so I didn't work on it.

Here is the code I had https://gist.github.com/jontelang/c6317bf14c527d2a89f1efd5d0... and I put this straight into my .bash_profile and it runs automatically when the shell starts.

  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.

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.

It’s currently this shell function:

  ts-fancy() {
    ((("$@" 2>&1 1>&3 3>&-) | ts -s "^[[91m[%H:%M:%.S]^[[m") 3>&1 1>&2) | ts -s "^[[92m[%H:%M:%.S]^[[m"
(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?

Very nice! Thanks you for sharing this!

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:

    export PS1='\[\e[00;37m\]$?\[\e[0m\]\[\033[1;32m\]\[\033[1;32m\][\t]\[\033[1;41m\]\u\[\033[1;41m\]@\[\033[1;41m\]\h:\[\033[0m\] \[\033[1;32m\]\w\[\033[0m\] \$ '
... 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:

    0[21:20:18]delian66@mypc: ~/Work $ slow_command
    0[21:22:19]delian66@mypc: ~/Work $

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've just made this [0], based on your idea (differently colored timestamps for both stderr and stdout).

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

Cherry-picking some of them:

    # Show Disk Use of subdirectories, sort by size
    alias duss="sudo du -d 1 -h | sort -hr | egrep -v ^0"

    # Cheatsheet autogenerated from i3 configuration file
    alias i3cheatsheet="egrep ^bind ~/.i3/config | cut -d ' ' -f 2- | sed 's/ /\t/' | column -ts $'\t' | pr -2 -w 145 -t | less"

    # Show mount information in a nice format
    alias mountt="mount | column -t | sort"

    # Show remaining dirty bytes while coping to a file, very useful in XFCE not sure in other enviroments
    alias watchdirty="watch grep -e Dirty: -e Writeback: /proc/meminfo"

    # Bookmark directories ej. "bm a" "go a" etc
    go() { eval dir=\$$1; cd "$dir"; }
    bm() { eval $1=$(pwd); echo "`set | egrep ^[a-z]+=\/`" > ~/.bookmarks; }
    test -f ~/.bookmarks && source ~/.bookmarks

    # I use this one all the time, combined find+grep, f.e. fgr "Class" "*.cpp" "-l" (2nd and 3rd parameters optional"
    function fgr {
            GREPTYPE="-i -H"
            if [ -n "$1" ]; then
                    test -n "$2" && NAM="-name \"$2\""
                    test -n "$3" && GREPTYPE=$3
                    CMMD="find . $NAM -not -path '*/\.*' -exec egrep --colour=auto $GREPTYPE \"$1\" {} + 2>/dev/null"
                    >&2 echo -e "Running: $CMMD\n"
                    sh -c "$CMMD"
                    echo ""
                    echo -e "Expected: fgr <search> [file filter] [grep opt]\n"

A well crafted $CDPATH helps me jump from project to project and from directory to directory within a project without having to type many ../:

I often grep/ag stuff only to think afterwards that I should have done that from Vim, so I have this to rerun the previous command and feed its output to Vim's quickfix:

    vimq() {
    	vim -q <($(fc -nl -1))
Speaking of Vim, this one lets me open an arbitrary file from the current project in Vim without having to glob:

    vimf() {
    	vim +find\ **/*$1
Create a directory and cd to it:

    mkcd() {
    	mkdir -p "$*"
    	cd "$*"
It's not in my .bash_profile but I use this little command all over the place to get my IP address (and I need my IP address a lot):

    #!/usr/bin/env sh

    SYSTEM=$(\uname | \tr /a-z/ /A-Z/ | \cut -c-5)

    # MacOS
    if [ "$SYSTEM" = "DARWI" ]; then
    	\ifconfig | \sed '/vboxnet/{N;N;d;}' | \grep 'inet ' | \grep -v '' | \awk '{print $2}' | \tr '\n' '-' | \sed 's/-.*//' | \tr -d '\n'
    	\exit 0

    # Linux
    if [ "$SYSTEM" = "LINUX" ]; then
    	\ip route get 1 | \awk '{print $NF}' | \tr -d '\n'
    	\exit 0

    # MINGW/CYGWIN on Windows
    if [ "$SYSTEM" = "MINGW" -o "$SYSTEM" = "CYGWI" ]; then
    	\ipconfig | \grep 'IPv4' | \awk '{print $NF}' | \tr -d '\n'
    	\exit 0

(It works, but..) What are all those backslashes for?

I use them to escape the first character of the command name, which has the effect of using the actual command and not an alias. In looking for a link to give you some background I found out that this is limited to interactive shells so those backslashes are just me not understanding what I do.

Ohh I didn't know that. Well...I've aliased a few programs to use a different version than the default, and redefined a few commands, so just prefixing "\" will get the original one. Very handy, thanks!

Here is mine:

  # misc
  alias mount="mount | column -t"
  alias ports="netstat -tulanp"
  alias vmstat="vmstat -w"
  alias ed="ed -p '>>> '"
  # genpass
  function genpass() { head -c 500 /dev/urandom | tr -dc a-z0-9A-Z | head -c $1; echo; }

  # git stuff
  alias gitpretty="git log --graph --oneline --decorate --all"
  alias gitprettyall="git log --oneline --decorate --all --  graph --stat"
  alias gfiles="git show --pretty='' --name-only $1"
  alias gitstat="git log --stat"
  alias gitchangelog="git log --oneline --no-merges ${1}..HEAD"
  alias gittopcontrib="git shortlog -ns"
  alias gitdiff="git difftool $1"

I use fzf [0] with zsh. I frequently use the Ctrl-T and Ctrl-R commands for finding files and searching history, respectively. Ctrl-R without fzf is great too, but with fzf you can see more of the history than just the currently selected entry. I hardly do `history | grep` anymore.

I've also been using trash-cli [1] for years with `rm` aliased to `trash-put`. It's saved me a handful of times when I've carelessly `rm`d something I shouldn't have.

[0] https://github.com/junegunn/fzf

[1] https://github.com/andreafrancia/trash-cli - Command Line Interface to FreeDesktop.org Trash.

alias shrug='echo -n "¯\_(ツ)_/¯" | xclip -selection clipboard && echo "\"¯\_(ツ)_/¯\" copied to clipboard!"'

alias YOLO='aurman -Syyu --noedit --noconfirm'

I have many, but one above all:

I've tried several different, SimpleNote, KeepNote, EverNote... and so on. I have come to a conclusion, that using the default iOS note app is enough for me. Using paper notes while @lectures and rewriting them sometimes to Notes. I'm also using another method of note taking, which I prefer more, but which is not always accessible on the go. I stumbled upon a script here and modified it a little. (changed vim to nano and added some other):

    #! /bin/bash

    if [ "$1" == "cat" ]; then
        cat "$fpath"
        exit 0
    elif [ "$1" == "rg" ]; then
        rg "$2" "$fpath"
    elif [ "$1" == "nano" ]; then
        nano "$fpath"
    elif [ "$1" == "--help" ]; then
        printf 'Commands: \n-----------------------------------------------\n
        $ notes \n
        $ notes --help\t\t--\tdisplay this help\n
        $ notes date\t\t--\tadd date row to notes\n
        $ notes <text>\t\t--\tadd new entry \n
        $ notes cat\t\t--\tprint notes using cat\n
        $ notes rg <pattern>\t--\tripgrep notes\n
        Remember to use #tags (for easier grepping)!\n\n'
    elif [ "$1" == "date" ]; then
        echo ''
        echo '# '"$(date +"%m-%d-%Y-%T")"
        echo '-'
        } >> "$fpath"
    elif [ "$1" == "" ]; then
        less +G "$fpath"
            echo ''
            echo "$@"
            echo ''
        } >>"$fpath"

In short, writing $ notes prints out displays the notes and writing $ notes <text> appends a new line. This is extremely powerful because of it's simplicity and easy accessibility in terminal (where I spend most of the time anyway)

From thread: Ask HN: Favorite note-taking software? https://news.ycombinator.com/item?id=17532094

Some Git aliases I use constantly, with a rebase-heavy workflow:

    di = diff
    dc = diff --cached

    ap = add -p
    unstage = reset HEAD -p
    discard = checkout -p

    ci = commit -v
    ca = commit -va
    amend = commit -v --amend
    reword = commit -v --amend --only
    extend = commit -v --amend --no-edit

    ri = rebase -i
    rem = rebase master
    rim = rebase -i master
    red = rebase development
    rid = rebase -i development
    continue = rebase --continue
    skip = rebase --skip

    pu   = push -v --progress
    poof = push -v --progress --force-with-lease
    pusu = -c push.default=current push -v --progress --set-upstream

I use sd (kinda like cd) when working with on mac with finder. With sd, you can select a file in finder, CMD+C and sd filepath.txt. The nice thing is that it goes to the same directory as the file so you don't have to delete the last part of the path manually. If you are sd-ing into a directory, it behaves like cd.

    sd () {
        if [ -f "$*" ]
                cd "$(dirname "$*")"
                cd "$*"
Also cwd which is like pwd but it also copies the current path to your clipboard.

    cwd='pwd | tr -d "\n" | pbcopy && pwd'

    alias continue-branch='charm $(git diff master --name-only)'  # Open all files changed in the current branch wrt master in PyCharm

    function record-window {
	recordmydesktop --windowid=$(wmctrl -l | grep $1 | awk '{print $1}') -o ~/Videos/$1_$(date +"%Y_%m_%d_%H_%M_%S").ogv

    alias ping='grc ping'
    alias ifconfig='grc ifconfig'
    alias netstat='grc netstat'

These last three use the awesome 'grc' output colorizer

_dynamic_ssh_creator() {

    for i in `ls ~/.ssh/keys|grep -v ".pub"|grep -v "id_dsa$"`; do


        func="function $cmd {"

        func="$func ssh -i ~/.ssh/keys/$i \$*;"

        func="$func }"

        eval $func



I have so many SSH keys that I can't be arsed to maintain an SSH config - especially when my brain is faster at it. This allows me to type <keyname>ssh and just live my life.

I like the ix.io pastebin, since it has a nice rest interface and the url is concise. I have a wrapper function that lets you run

    ix [<path>]
and will sumbit the content of the supplied path, or stdin if no path is given.

Here's function at said pastebin (http://ix.io/1yiG/sh), and in raw form below:

    ix() {
    	curl=$(command -v curl)
    	[ -f "$HOME/.netrc" ] && curl="${curl} --netrc"
    	while getopts ":d:i:n:e:" opt; do
    		case "${opt}" in
    			d) ${curl} --request DELETE "ix.io/${OPTARG}"; return;;
    			i) curl="${curl} --request PUT"; id="${OPTARG}";;
    			n) curl="${curl} --form read:1=${OPTARG}";;
    			e) curl="${curl} --form ext:1=${OPTARG}";;
    			:) error "Expected argument: -${OPTARG}"; return 1;;
    			*) echo 'Usage: ix [-d ID] [-i ID] [-n N] [<options>]';
    	shift $((OPTIND - 1))
    	unset -v OPTIND OPTERR
    	if [ -t 0 ]; then
    		filename="$1"; shift
    		if [ "$filename" ]; then
    			${curl} --form f:1=@"$filename" "${@}" "ix.io/${id}"
    		echo "^C to cancel, ^D to send."
    	${curl} --form f:1='<-' "${@}" "ix.io/${id}"
    	unset -v curl opt id filename

In ~/.bash_functions

  $ loz QUERY
will give the password from the ~/.passwords flat text database, last password is valid one.

  $ lozinka
will ask for questions and enter it into ~/.passwords

I suggest chattr +a ~/.passwords so that file cannot be deleted, only appended.

  function loz () {
            if [[ "$1" ]]; then
                /bin/grep -i --color=auto "$1" $PASSWORDS;
                echo "No query given."

  function lozinka () {
       echo -n "Hostname:"; read hostname;
       echo -n "Service:"; read service;
       echo -n "Username:"; read username;
     echo -n "Email:"; read email;
     password=$(pwgen -n -n -n -s 20 1)
     echo -n "Password (${password}):"; read password1;
     if [[ $password1 ]]; then
     if [[ ( $username || $email ) && $password ]]; then
         line=$(join_by : $hostname $service $username $email $password);
         echo $line >> $passwords;
         tail -n1 $passwords;
         echo "Nothing recorded as there is no username or email";

I have few on my MBP that I use a lot

# CD to the root of the current git project

    alias ,,='git rev-parse --git-dir >/dev/null 2>&1 && cd `git rev-parse --show-toplevel` || echo "Not in git repo"'

# Put my MBP to sleep in X minutes

    sleep-in() {echo "Sleeping laptop in $1 minutes..." && sleep $((60 * $1)) && pmset sleepnow}
# Check CI status nicely using hub (hub.github.com)

    function ci {
      unbuffer hub ci-status -v $1 | sed 's/https:.*//'
# Rerun the last git command with the suggestion it had

    alias yup='eval $(fc -ln -1 | sed "s/git/git -c \"help.autocorrect=-1\"/")'
# Look up directories for a Makefile and run it - I couldn't find a way to actually search up directories, so `detect` is my own binary that does that

    function make {
        if detect Makefile > /dev/null 2>&1 ; then
            LOCATION=$(detect Makefile)
            echo "Makefile found at $LOCATION"
            cd $LOCATION && /usr/bin/make $* && cd - >/dev/null
            echo "Makefile not found"

Definitely not for everyone, but:

  set +H
  export HISTIGNORE="&"
  alias reset="printf '\033\143'"
  alias ls="ls --color=never -p -D '%Y-%m-%d %H:%M'"
  alias pmake="gmake -j30"
  PS1="\[\e[0;32m\][\w]$\[\e[m\] "
  history -w
  history -c
I turn off history substitution (sometimes ! get into my program arguments and I don't like surprises), and start with no history on new terminals. I don't trust myself not to run an rm * from a previous session, open another terminal, and hit up one too many times.

A little colorization of the terminal prompt, and spicing up of ls output (the colors actually give me trouble, and often I can't read the dark blue items at all.)

But most specifically, I adore the reset alias. Unlike clear, it isn't undone when you scroll up. The built-in reset command takes forever to run and does a bunch of things I don't want.

HISTIGNORE is my absolute favorite. It doesn't log your last command to history if it's the same as the one already there. I'll often run make multiple times to fix compilation errors, and with HISTIGNORE, the command to run the resulting binary is only ever two up keystrokes away.

I switched to a color schema where this dark blue is gone :-)

I have some git ones that save me a few thousand key strokes a day.

  alias gs="git status"
  alias gall="git add ."
  alias gm="git commit"

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:

  function gitpruneremote {
    git remote prune origin
  function gitprunelocal {
    git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -D

Git pulling in every repo:

  function gitpullall {
    cd ~/yourCodeDir
    find . -type d -depth 1 -exec git --git-dir={}/.git --work-tree=$PWD/{} pull \;
This one is simple, and was useful in my LAMP dev days, to tail apache logs with line breaks formatted:

  function tailerr() {
    tail -f /path/to/errorlog | sed 's/\\n/\n/g'

    alias ..='cd ..'
    alias ...='cd ../..'
    alias ....='cd ../../..'
    alias d='docker'
    alias up='docker stack up --with-registry-auth'
    alias node='node --experimental-modules --experimental-repl-await --no-warnings'
    alias net='netstat -tunl'
    alias jurl='curl -sLH "Content-Type: application/json"'
    alias sb='source ~/.bashrc'
    rand() {
      openssl rand -base64 ${1:-15} | tr '+/' '-_' | tr -d '[[:space:]]='
    randomstring() { LC_CTYPE=C tr -dc '[:print:]' < /dev/urandom | dd bs="${1:-16}" count=1 2>/dev/null; echo; }
    serv() { docker run --rm --name "nginx-${1:-8000}" -p "${1:-8000}:80" "${@:2}" -v $PWD:/usr/share/nginx/html:ro caub/nginx-dev; }

    n() {
      if [[ "$1" =~ $npmRegexp ]]; then 
        npm "$@"
        npm run "$@"

alias lcoate=locate

alias 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"

    alias cdl="cd (ls -ltr1 | grep '^d' | tail -1 | awk '{print $9}');"
cd to last directory by date.

mdd is nice.

My most commonly used thing in my profile is this combination git tag, push, and npm publish using the current version in my package.json file:

   	np() {
		PACKAGE_VERSION=$(node -p -e "require('./package.json').version")
		echo $LONGVER
		git tag -a "$SHORTVER" -m "$LONGVER" && git push --tags && npm publish

    node -p "require('./package.json').version"
no need for -e, or also just:

    jq -r .version package.json

I have 'usb' aliased as my main USB's directory.

Making 'cd' more explicit:

  cd ( ) {
  builtin cd "$@"
  echo "$OLDPWD -> $PWD"
Up directory

  alias ..='cd ../' 
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 -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

  #dlm - download mp4 from clipboard URL. usage: 'dlm myfile' downloads myfile.mp4
  #with resume after 5 secs until finish.
  echo "Download $fname as $1.mp4 : "
  until curl -C - -kLo $1.mp4 "$fname"
        sleep 5

I am using zsh/iterm on my mac so here are mine:

    # branches that were touched lately 
    nb() {
      git for-each-ref --sort=-committerdate refs/heads/ -- format='%(committerdate:short) %(authorname) %(refname:short)' | head -n 10

    # squash!
    squash() {
      if [ -n "$1" ]; then
        git reset --soft HEAD~$1 && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"

    # open pr page on github for current branch
    pr () {
      local repo=`git remote -v | grep -m 1 "(push)" | sed -e "s/.*github.com[:/]\(.*\)\.git.*/\1/"`
      local branch=`git name-rev --name-only HEAD`
      echo "... creating pull request for branch \"$branch\" in \"$repo\""
      open "https://github.com/$repo/pull/new/$branch?expand=1"

    # check who uses port 
    port() {
      lsof -i tcp:"$@"

    # rebases local branch from origin /master and force pushes it
      git fetch origin master
      git stash
      git rebase origin/master
      git push --force
      git stash pop

Probably too late to get some visibility, but I love this:

    function my-accept-line() {
      # check if the buffer does not contain any words
      if [ ${#${(z)BUFFER}} -eq 0 ]; then
        # put newline so that the output does not start next
        # to the prompt
        # check if inside git repository
        if git rev-parse --git-dir > /dev/null 2>&1 ; then
          # if so, execute `git status'
          git status
          # else run `ls'
          ls -l
      # in any case run the `accept-line' widget
      zle .accept-line
    # create a widget from `my-accept-line' with the same name
    zle -N accept-line my-accept-line
    # rebind Enter, usually this is `^M'
    bindkey '^M' accept-line
This replaces `enter` (empty command line), with either `ls` or `git status` if in a git repository.

This beautifully works as expected, I never got any bug because of this (as this could be expected for low level aliasing), and it does exactly what I'd expect: get current status of the current folder.

Now typing `git status` elsewhere is such a pain!

Late on this as well but in case it's useful to you, I use this for quick "git add":

  ga () {
          if test "$#" -eq 0
                  echo "No arguments (0_0)?"
          elif test "$#" -eq 1
                  git add -u && git commit -m "$(echo $1 | sed 's/^./\U&\E/')"
                  git add ${@:1:$(( $# - 1 ))} && git commit -m "$(echo ${@:$#} | sed 's/^./\U&\E/')"

  # Add all modified files and capitalize the commit message
  ga "fix typo in README"
  # Add some files and treat last arg as commit message
  ga main.rs point.rs "speedup by 10e9"

I have two programs that open Firefox. I also have some other programs, too.


  #!/bin/bash --
  f0() {
    echo 'select moz_bookmarks.title || '"'"' = '"'"' || url from moz_places, moz_bookmarks on moz_places.id = moz_bookmarks.fk where parent = 2;' | sqlite3 /home/user/.mozilla/firefox/twht79zd.default/places.sqlite
  f1() {
    firefox `echo 'select url from moz_places, moz_bookmarks on moz_places.id = moz_bookmarks.fk where moz_bookmarks.title = '"'$1'"';' | sqlite3 /home/user/.mozilla/firefox/twht79zd.default/places.sqlite`
  f$# $1

  #!/bin/bash --
  firefox 'http://en.wikipedia.org/wiki/Special:Search?search='`node -p 'escape(process.argv[1])' "$1"`
(Maybe there is a better way than calling Node.js to escape the URL)


  #!/bin/bash --
  curl 'http://icanhazip.com/'

  #!/bin/bash --
  for X in `seq 1 $X`; do "$@"; done


  #!/bin/bash --
  curl 'http://ipinfo.io'
ipinfo is a lot more verbose. Depending on your needs...

Ex result: $curl ipinfo.io { "ip": "XXX.XXX.XXX.XXX", "hostname": "XXX.XXX.XXX", "city": "XXX", "region": "XXX", "country": "US", "loc": "XXX,XXX, "postal": "XXX", "phone": "XXX", "org": "ASXXX XXX XXX XXX" }

Some basic aliases I couldn't live without:

    alias rm='rm -i'
    alias mv='mv -i'
    alias cp='cp -v'
    alias ls='ls --color=auto -Fh'
    alias ll='ls -l'
    alias lla='ls -la'
    alias clean='rm -rfv *~ .*~ \#*\# .\#*\#'
    alias j='jobs'
    alias rm='rm -i'
    alias cp='cp -v'
    alias mv='mv -v'
Workspace management

    function workon () {
        cd "${HOME}/work/$LOC"
        tmux attach -dt "$LOC" || tmux new -s "$LOC"
Handle the git submodules nightmare (a little) more easily

    alias subupdate='git submodule init; git submodule sync; git submodule update --init --recursive;'
Colored prompt with git branch:

    PMT=" "; if [  $UID -eq 0 ];then PMT="# " ;else PMT="$ " ; fi
    export PS1="[$GREEN\u@\h $BLUE\W$WHITE:$YELLOW\$(git branch 2>/dev/null | grep '^*' | colrm 1 2)$WHITE]"$PMT
Run a quick web server

    alias simpleWebServer='python -m http.server 8888'
If you are using tmux, WSL, and ssh all together, you may sometimes need something like this (I always keep it in my bash_aliases and since never had color issues :)

    if [ "$TERM" == "screen" ]; then
        export TERM="screen-256color"

Some simple things, but little timesavers:

  function mk() {
    mkdir -p $1 && cd &1

  alias gpm='git pull master'
  alias gcm='git checkout master'
  alias grh='git reset --hard HEAD'
  alias gs='git status'
  alias gd='git diff'

  alias h='history | grep' # Use like, "h ssh" to see all ssh in your history

Well the most used, and first thing i add when i get to a new system is:

   alias src="source $rcbash"
   alias vrc="vim $rcbash"
   alias vimo="vim -O"  # vsplit files

And then, a little snippet which made my "bashrc" less repetitive when it comes to folder aliases.

   gr4_folderize() {
    # creates aliases and variables for a path
    # $1 = used abbreviation
    # $2 = folder path
    # gr4_folderize "esp32" "/srv/dd/esp32"
    # creates aliases `cdesp32`, `lsesp32` and `diresp32` env

    # ${param:?word} writes `word` to stdout when param is unset or null
    local abbrev="${1:?No abbreviation alias.}"
    local folder="${2:?No directory to folderize.}"

    export dir${abbrev}="$folder"
    which > /dev/null 2>&1 cd${abbrev} || alias cd${abbrev}="cd $folder"
    which > /dev/null 2>&1 ls${abbrev} || alias lll${abbrev}o="lla $folder"

Plus `ask_yes` if you want to ask if user is sure.

   ask_yes () {
    read -r -p "$1 = Are you sure? [y/N] " response
    if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]
        return 0  # true = 0
        return 1  # false = 1
Plus `countdown timer` to make user think about what he has done, before he does it. (Code is a mess cause i used some snippet then created another from it)

  countdown_str () {
    # countdown "00:01:00" # = hh:mm:ss
    set -- $*
    secs=$(( ${1#0} * 3600 + ${2#0} * 60 + ${3#0} ))
    while [ $secs -gt 0 ]
      sleep 1 &
      printf "\r%02d:%02d:%02d" $((secs/3600)) $(( (secs/60)%60)) $((secs%60))
      secs=$(( $secs - 1 ))

  countdown_5 () {
    countdown 5 2>/dev/null

  countdown () {
    chars=$(printf "%02d:%02d:%02d" $hours $mins $secs)
    echo "Countdown from $chars"
    countdown_str $chars 2>/dev/null

I have aliases with the name of every project that open up a productive environment.

Eg. open a project with “Visual Studio Code” get latest version from git, reset db and run seeding. Then install dependencies and run dev server, while opening chrome at the right localhost address. I usually run the command walk away to get a drink or food and when I’m back everything is running so I can just start working!

I dislike pretty much the entire Windows command line, except for one small bit of it: `start` (for the purpose of launching stuff in the background and disowning it, not for the `xdg-open`-like functionality).

So, I had this in my rc files for a while:

  start() { nohup "$@" &> /dev/null &; }
After that, I replaced the function with the custom command from here: http://web.archive.org/web/20151221072546/https://felixmilea...

I'd still like to have auto completion for this, though, but I never got around to learning about the ways to achieve that in bash and zsh.

Edit: Also, the one I probably use the most:

  alias l="ls -ltrash"
although I've started to replace it with

  e() { exa -bghHliSa --color=always "$@" | bat; }
  et() { exa -bghHliSTa --color=always "$@" | bat; }

I use bash, but really like the RPROMPT idea from zsh, so mimick that as best as I can.

It turns out that bash has a PROMPT_COMMAND variable which gets called before writing out PS1, so I use this to write my own rprompt. The main idea is just to use tput to draw a thing on the right and restore the cursor position afterward.

As is, I have something like below right-justified at each prompt:

    user@host:pwd (git-branch)
It even degrades nicely if horizontal space starts getting cramped. Actually, the code is (I believe) just posix shell, so I define relevant functions in .profile and have .bashrc and .mkshrc use them as appropriate. Since it's a bit long, here are some pastebins that should be drop-in workable:

- profile: http://ix.io/1yiC/sh

- bashrc: http://ix.io/1yiA/bash

- mkshrc: http://ix.io/1yiB/ksh

There are a couple caveats. Bash clears the whole line when deleting characters, which causes the rprompt to be cleared as well. On the other hand, mksh works as expected. Also, if you enter really long commands into the prompt, they will eventually bump into and overwrite the rprompt, instead of clearing it wholesale. I've not found this too much of a problem though.

In the code above, the rprompt() function defines the actual contents of the prompt and performs the graceful degredation. The rprompt_draw() function does the actual drawing and prompt_draw() links these two together to be used by bash, mksh, etc.

Feel free to ask my any questions or hate on my code.

I like to put useful information in the prompt, but yours looks too cluttered for my liking. I particularly dislike the fact that most of the information of your prompt is nearly constant, thus very redundant. Putting the CWD inside the prompt is useless. You can just run pwd yourself if you are lost, but most of the time you already know where you are. Similarly for the username and the hostname. If you only deal with two or three servers, you can color code your prompt symbol to those, and obtain a much shorter and cuter prompt.

Useful information that is still not in your prompt:

- status of the last run command: $?

- number of jobs in the background, if any

I have this, with some colors thrown in:

    PS1='$(if [ \j != "0" ] ; then echo "[\j]"; fi)$?\$ '

That's all quite easy to change in the rprompt() function. I tried hard to factor everything out, so the prompt content specification itself is clear and obvious.

Basically, for the reasons you mention, I dislike having that info set in PS1, but I find it considerably less distracting when right-justified. Having it visible, though, makes it easy to ascertain the execution context of commands in the terminal history buffer.

The status of last run command I have on my PS1. If it exits 0, then it's just a simple

otherwise, it's:

I do like your idea of showing current background jobs, but I find myself relying more on tmux windows than background jobs, so I suspect that number would be mostly constant for myself anyway.

> I do like your idea of showing current background jobs, but I find myself relying more on tmux windows than background jobs, so I suspect that number would be mostly constant for myself anyway.

Sure! the idea is that background jobs are very rare, and their existence should be clearly indicated in the prompt (in bright red). Usually, there are zero jobs and the prompt is silent about that.

These are probably the 3 I find most useful:

Copies the directory of the current git dir into the clipboard.

    which pbcopy &> /dev/null
    if [[ $? -eq 0 ]]; then
    which clip &> /dev/null
    if [[ $? -eq 0 ]]; then

    cpgitdir() {
        GIT_DIR=`git remote show -n origin | grep "Fetch URL" | sed -e "s/  Fetch URL: //"  | tr -d '\n'`
        echo "Copying git dir to clipboard: $GIT_DIR"
        echo $GIT_DIR | tr -d '\n' | $CLIPBOARD_COMMAND
Allows you to split your .bash_profile into multiple .bash_profile files for clarity

    if [[ -d ~/.bash_profile.d ]]; then
        for file in `find ~/.bash_profile.d -type f`; do
            source $file
Simple calculator

    calc () {
        bc -l <<< "$@"

Before I check in my code I check whether I've made any silly mistakes / forgot to remove console.log, etc.

    alias diff='diff2html -s side'
This requires the diff2html cli - https://diff2html.xyz/ - install with `npm install -g diff2html-cli`

Love this thread! Some of mine (excluding similar to what has already been mentioned):

  alias cleangopro="rm -rf /Volumes/GOPRO/DCIM/*"
  alias mkdir="mkdir -pv"
  alias ssh<proj>="ssh <user>@<ip>"
  alias clearmail='sudo rm /var/mail/<user>'
  alias flushcache='dscacheutil -flushcache && sudo killall -HUP mDNSResponder'
  alias listenforpwd="sudo tcpdump port http or port ftp or port smtp or port imap or port pop3 or port telnet -lA | egrep -i -B5 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd=|password=|pass:|user:|username:|password:|login:|pass |user '"
  alias listenforuseragent="sudo tcpdump -vvAls0 | grep 'User-Agent:'"
  alias listenforgetreq="sudo tcpdump -vvAls0 | grep 'GET'"

SSH has a configuration file (.ssh/config) which lets you set configuration for specific hosts and even aliases:

    Host reproserver
    User remi
    IdentityFile ~/.ssh/id_rpz

One I have been using for over 20 years, aliasing l to my favorite ls switches:

    alias l='ls -GFla'

Ditto. (Though not 20 years).

I use these 3

   alias ls='ls --color=auto --group-directories-first'  # override
   alias l='ls -hF'
   alias ll='ls -hAlF'
   alias lt='ls -clthF'
Also, incredibly useful:

   alias c='clear'
I type `l` and `c` all the time. Then I get on a different machine and `command not found`.

  mcd(){ mkdir "$1"; cd "$1"; }
  alias vd='vim -d' # vimdiff
  alias grep=egrep

# z for quickly switching between commonly used dirs eg. `z ex` -> cd /mnt/c/dev/api.extensions

  # https://github.com/rupa/z
  source ~/z.sh
git helpers

  # update all git repos in subdirs
  alias gitp="ls -d */ | xargs -P10 -I{} git -C {} pull"
  # fetch updates for git repos in subdirs
  alias gitf="ls -d */ | xargs -P10 -I{} git -C {} fetch --all"
selection of most commonly used git aliases

  ci = commit -m
  cf = clean -fxd
  cl = clone
  co = checkout
  cm = commit --amend --no-edit
  lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %Cblue<%an>%Creset' --abbrev-commit --date=relative --all -n 25
  pf = push -f --follow-tags
  rb = rebase master
  st = status -sb

Use docker to run binaries without installing:


I have an alias for cd which prints any file called '.cd-reminder' in a directory. I make notes like "pull and rebase daily!" in my work repos. I'll post it later from my laptop. It's just an if statement in a function, though, so not hard to reproduce yourself.

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"

    # 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'..." ;;
          echo "'$1' is not a valid file!"
[1] https://github.com/NewProggie/Dev-Utils

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.

Similarly, the unp script automatically detects and unpacks most archives https://manpages.debian.org/jessie/unp/unp.1.en.html

> alias .....="cd ../../../.."

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"

Edit: found this elsewhere in this discussion posted by jgresty https://news.ycombinator.com/item?id=18901834

  # go to root git directory
  alias cdgit='cd $(git rev-parse --show-toplevel)'

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.

I'm on a phone right now so can't paste the function easily but check out my dotfiles repo which has keybinding of those ...... aliases for any level.


  alias ll='ls -l'

"alias ll='ls -al'" is the first thing I type every time I ssh into any system that isn't mine.

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
    if [ "$DOCKER_HOST" != "" ]
    /usr/bin/docker $HOST_ARG $@

    $ cat ~/bin/docker-compose
    if [ "$DOCKER_HOST" != "" ]
    /usr/local/bin/docker-compose $HOST_ARG $@

Strictly speaking, tmux is out of scope of the question, but I hope some people would be interested.

I found myself needing to use deeply nested tmux sessions a few times and navigating between nestings is a huge pain under a vanilla setup. Using some configuration trickery, I was able to hack in keys to "focus" between nesting levels. Here's a repo I have it sitting under:


The code should be relatively drop-in and the README not terrible.

I'd love to hear thoughts.

Quickly find messages in your local Maildirs. Full replacement for Google mail and other centralized spying email systems. It uses https://github.com/djcb/mu and mutt https://www.mutt.org in ~/.bash_functions directly from shell, and displays emails

  function search-messages () {
     /usr/local/bin/mu find --clearlinks --format=links --linksdir=~/Maildir/search "$@" && mutt -f ~/Maildir/search

  function certchain() {
      # Usage: certchain
      # Display PKI chain-of-trust for a given domain
      # GistID: https://gist.github.com/joshenders/cda916797665de69ebcd
      if [[ "$#" -ne 1 ]]; then
          echo "Usage: ${FUNCNAME} <ip|domain[:port]>"
          return 1

      local host_port="$1"

      if [[ "$1" != *:* ]]; then
          local host_port="${1}:443"

      openssl s_client -connect "${host_port}" </dev/null 2>/dev/null | grep -E '\ (s|i):'

I’m flattered

haha, this made my day! small world :)

I use 'u' to navigate up parent directories:

  alias u="cd .."
  alias uu="cd ../.."
  alias uuu="cd ../../.."
  alias uuuu="cd ../../../.."

I found a much better way of handling this via SO one time, and I've kept it ever since:

  # Up command, from stackoverflow.  Takes optional number of 
  levels to cd ../
    local d=""
    for ((i=1 ; i <= limit ; i++))
    d=$(echo $d | sed 's/^\///')
    if [ -z "$d" ]; then
    cd $d

Interesting. I have the same, but aliases to `.` instead.

  alias ..='cd ../'
  alias ...='cd ../../'
  alias ....='cd ../../../'
  alias .....='cd ../../../../'

  alias ea='vim ~/.bash_aliases'
  alias ear='source ~/.bashrc'
* i type 'ea' whenever i think a commands should aliased.

* add new aliases

* exit dan type 'ear' to refresh the bashrc.

go for another productive terminale.

alias als="vi ~/.bash_aliases && . ~/.bash_aliases"

To fix some bugs

    shopt -s checkwinsize
    shopt -s autocd

To make life better to my taste

    alias tmux="tmux new -A -s root"
    export HISTCONTROL=ignoredups

To distinguish between development, test and production environments by color (VERY userful)

    export PS1='[\[\e[1;91m\]\u\[\e[0m\]@\[\e[1;31m\]\H\[\e[0m\] \[\e[1;95m\]\w\[\e[0m\]]\\$ '
    export PS1='[\[\e[1;92m\]\u\[\e[0m\]@\[\e[1;32m\]\H\[\e[0m\] \[\e[1;95m\]\w\[\e[0m\]]\\$ '
    export PS1='[\[\e[1;93m\]\u\[\e[0m\]@\[\e[1;33m\]\H\[\e[0m\] \[\e[1;95m\]\w\[\e[0m\]]\\$ '

in .gitconfig:

  recent = for-each-ref --count=25 --sort=-committerdate refs/heads/ --format="%(refname:short)"
so `git recent` lists the last 25 branches, and then in .bashrc:

  alias co='select br in $(git recent); do git co $br; break; done'
  alias coo='select br in $(git br -r|grep -v "("|grep -v HEAD|cut -c3-|sed "s/^origin.//"); do git co $br; break; done'
and now `co` gives me a menu of recent local branches to check out, and `coo` does the same for remotes on origin

Some of mine not already seen:

    alias mirror='wget -m -r -np -p -k -E'
    alias g_short_hash='git rev-parse --short --verify HEAD'
    alias g_head_branch='echo "`git symbolic-ref HEAD 2> /dev/null | cut -b 12-`"'
    alias g_branch_w_hash='echo "`git symbolic-ref HEAD 2> /dev/null | cut -b 12-`-`git log --pretty=format:\"%h\" -1`"'
On OS X:

    alias sleepnow="pmset sleepnow"
    alias netstat_tanp="lsof -Pnl +M -i4 -i6"

Some of aliases in my bash profile

#Git Aliases alias gc="git checkout" alias gp="git pull" alias gp="git pull --rebase" alias gb="git branch" alias gs="git status" alias gd="git diff" alias gl="git log --oneline" alias gu="git ls-files --others --exclude-standard"

#HDFS Alias alias hls="hdfs dfs -ls" alias hcat="hdfs dfs -cat" alias hrm="hdfs dfs -rm" alias hrmf="hdfs dfs -rm -r -f" alias hmd="hdfs dfs -mkdir"

I also have aliases for git, only I noticed gs starts Ghostscript on places where I don't have these set, so I changed all my git aliases to gg:

  ggs -> git status
  ggco -> git checkout
  ggd -> git diff
  ggap -> git add --patch

Convert any video to webm with specified bitrate:

  $ video2webm 300k myvideo.mp4 othervideo.mpg third.mov

  function video2webm () {
     for file in "$@";
     do out=${file%.*}.webm;
        ffmpeg -y -i "$file" -c:v libvpx-vp9 -b:v $bitrate -pass 1 -speed 4 -c:a libopus -f webm /dev/null && \
            ffmpeg -i "$file" -c:v libvpx-vp9 -b:v $bitrate -pass 2 -speed 1 -c:a libopus "$out";

My git related aliases:

  alias master='git checkout master'
  alias f='git fetch --all'
  alias s='git status --untracked-files=all'
  # go to the last branch I worked on, excluding master and the current branch
  alias lb='git checkout `git for-each-ref --sort=-committerdate refs/heads/ | grep -v refs/heads/master$ | grep -v \`git rev-parse --abbrev-ref HEAD\`| head -n1 | cut -d \/ -f 3-`'

I have a bunch of project/location specific environment preparing handles in my .aliases file.

Stuff like:

alias @projectName="cd $project && alias java='/some/specific/version' && export SOME_VAR=value"


alias @untrustedWifi="tor && torbrowser && set up an SSH tunnel to access mail etc"

I can't really share the actual contents, because they depend on a boatload of scripts in my ~/bin dir and they're all pretty specific to my environment.

I do this plus set the prompt accordingly to remind me in which state it is

alias grpe=grep

Nothing comes close to the amount of time I saved with this one.

Hehe I liked the 'lcoate' one on this page too, same idea. It might be super-useful to have a function that, if command not found and if there's an anagram of what you typed that is a command, asks if you meant that instead, y/n? (That would make computers seem a lot more intelligent!)

Thanks, but my computer's too old to read that page. It's a thing already?

Yes, it's a command you can use when the previous one failed for some reason, that tries to correct the typos if any, or adds sudo or a missing option...

seriously. this was the first thing i searched for when i came to the comment thread, so i could add it if (somehow) someone hadn't already done so.

best. alias. ever.

    function convert-decimaltobinary(){
        while [ "$n" -gt 0 ]; do
            bit="$(( n&1 ))$bit";
            : $(( n >>= 1 ))
        printf "%s\n" "$bit"
    function convert-binarytodecimal(){
        echo "$((2#$1))"
    function convert-hextodecimal(){
        echo $(( 16#$1 ))

I think I'll use them more if they're cdb, cbd, chd. Thanks!

Zsh function to create a directory and cd into it in one go:

  function mkcd() { mkdir -p "$@" && eval cd "\"\$$#\""; }

zsh already has the take command for this AFAIK

I work on a number of Go projects. This is one that lasted me for close to a decade now:

    function workspace_cd() {
        cd $@ && [ -f ".bashworkspace" ] && source .bashworkspace
    alias wscd="workspace_cd"
Each .bashworkspace file contains something like this:

    export GOPATH={PATH HERE}
    export PATH=$GOPATH/bin:$PATH

  unameOut="$(uname -a)"

  case "${unameOut}" in

	*Microsoft*) machine="WSL";;

	Linux*)      machine=Linux;;

	Darwin*)     machine=Mac;;

	CYGWIN*)     machine=Cygwin;;

	MINGW*)      machine=MinGw;;

	*)           machine="UNKNOWN:${unameOut}"


  unset unameOut

  PROMPT_COMMAND='echo -ne "\033]0;[${machine}] ${USER}@${HOSTNAME}: ${PWD}\007"'

Folder Git[0], a quick hack to for example pull all my 100+ repos in one go. First version eight years ago, and I still use it every day.

[0] https://gitlab.com/victor-engmark/fgit/blob/9575803b3bf277d5...

I never use vim or emacs viper-mode on my machine. But I let other people to use my emacs viper-mode:

      emacs -nw --eval '(and (switch-to-buffer "foobar") (setq viper-mode t) (setq viper-inhibit-startup-message t) (setq viper-expert-level 1) (viper-mode))' "$@"

  alias vim=vi
  alias vim.tiny=vi
  alias vim.basic=vi

In my bash_profile is a simple echo which makes the shell say hi to me every time I open an instance. Brightens my day a little bit:

  echo 'Hello dude '
As an iOS dev, this one is super useful:

  alias cdd='rm -rf ~/Library/Developer/Xcode/DerivedData/* && echo "Cleared DerivedData/"'

cdd seems like a bananas alias for something that does an rm -rf!

Have you ever done it by mistake?

It doesn't really matter; the directory is Xcode's auto-generated build products and can be recreated quite easily.

Cannot remember pacman queries:

  # Pacman functions
   function pacinstall () {
     sudo pacman -S "$@"
   function pacremove () {
     sudo pacman -R "$@"
   function paclist () {
     sudo pacman -Ql "$1" | less
   function pacsearch () {
     sudo /usr/bin/pacsearch "$@" | less

These are my favorites:

alias ia="open $1 -a /Applications/iA\ Writer\ Classic.app"

alias makepass="pwgen -s 30 | awk '{print $NF}' | pbcopy"

alias phplint="find . -name \".php\" -print0 | xargs -0 -n1 -P8 php -l"

alias quicklint="find . -name \".php\" -depth 1 -print0 | xargs -0 -n1 -P8 php -l"

alias loc="find . -name '*.php' | xargs wc -l"

One useful alias I have not seen mentioned here is this:

  alias myip='curl -s https://api.ipify.org'
Just prints out my current public IP address. I also have a bunch of others mentioned in this thread, and I've abbreviated a bunch of self-explanatory docker-compose commands, e.g. dcdown, dcup, dcrestart, dcpullup, etc

  curl ifconfig.me
is also easy to remember

Curl ipinfo.io

I've used these so much:

    function gc() { grep -rnI "$@" * ;}
    function gcA() { grep -rnI -A 5 "$@" * ;}
    function gcB() { grep -rnI -B 5 "$@" * ;}
    function gcC() { grep -rnI -C 5 "$@" * ;}
    function gcf() { grep -rnIl "$@" * ;}
Just helper functions built on top of grep

And what do they do? It's not obvious.

edit: Thank you both!

-r enables recursion

-n enables line numbers

-I (eye) ignores matches on binary files

-l (ell) lists the filenames of matching files only (overrides -n)

-A, -B, and -C specify how many lines of context after, before, or around the match to display.

"$@" adds any additional command line arguments passed to the functions.

* selects all the files and directories in the current directory.

So, without other arguments, the first four functions list matches with line numbers for all files (ignoring binary files) in the current directory and below, with 0 lines context (match only), 5 lines context after, 5 lines context before, and 5 lines context around the match respectively. The final function lists the filenames only and provides no context or line numbers.

-r searches directories recursively instead of single files; -n displays line numbers; -I ignores binary files. -A, -B, -C, and -l set how much context is shown: 5 lines of content before the match, after the match, or both; or just the filename and no content.

I use my git aliases dozens of times each day, especially the last few that pop open relevant repository webpages: https://github.com/andjosh/dotfiles/blob/master/.gitconfig#L...

  alias c='cd'
  alias cd='cd ..'
Yes, I am lazy. Yes it has saved me thousands of keystrokes

My diary:

    alias today='vim ~/notes/$(TS="Europe/London" date +%Y-%m-%d).txt'

One of my most valuable aliases used is for backing up deleted files and directories using the trash-cli Linux utility.

The trash-cli utility has some quirks related to mounted drives but once you understand how to set up correctly, aliasing rm to trash can save you from losing files you've deleted by mistake.

Not bash but git aliases, as a consequence of our gerrit workflow:

    alias.gerritpush=push origin HEAD:refs/for/develop
    alias.fixlast=!git commit -a --fixup=HEAD && GIT_EDITOR=true git rebase -i --autosquash HEAD~2
    alias.loglast=log -n 1 -p

    export MAKEFLAGS=-j`nproc`
make will automatically parallelize builds for the number of cores on the machine. It also breaks various things interestingly, particularly build systems which don't pay attention to correct dependences.

in .bash_functions with PostgreSQL

to get the age of anybody:

  function age () {
     if [[ $1 && $2 ]]; then
         AGE=$(psql -Stc "SELECT age(date('${DATE}'));");
         echo $NAME: $AGE, was born on $DATE | sed 's/ mon / month /' | sed 's/ mons \| mons,/ months /';
         echo "No name or date supplied";

  function child () {
     age "My child" "2012-03-12";

Simple aliases for find and grep, that allow to just look for something without worrying about case sensitivity, escaping, etc.

  function ff {
      find . -iname \*$1\*

  alias gr='ack -i'

If you've made the move to powershell:


Directory specific history... Probably my most useful profile addition.


alias vim='emacs'

It's not useful in any way, but I have one alias... "doot". It runs a Python script that draws a skeleton playing the trombone over an 80s scrolling grid and sunset.

Because I want to do file completion on files with datetimes (think colons)

See the Bash FAQ for more info.

For pretty-printing tabular data (tab- and comma-separated):

alias seetsv="column -s $'\t' -t"

alias seecsv="column -s ',' -t"

I use prefix qq for my commands because:

  1. It is easy to discover all customizations 
     via autocomplete
  2. It is not going to clash 
     with existing functionality

  # (Sort stuff by size, latest down, in a directory)
  alias qqsize="ls -lSrh"
  alias qqdate="ls -lrt"
  # First 100 of largest files/directories in a folder
  function qqlargest_files_100(){
    du -a ./ | sort -n -r | head -n 100
  # Archivate item 
  qq-tar-gz-it () {
    tar -zcvf  $2 $1;
  # Convert video to a gif
  function qq_convert_video_to_gif(){
    ffmpeg -i $1 $1.gif  
  # Push to GitHub
  function togithub__master(){
      git add -A;
      git commit -m $1;
      git push github master;
  # Symlink config file
  # 1. Move dotfile to a config directory.
  # 2. Strip the dot
  # 3. Symlink that file back to its place
  function qqsymlink_config_file(){
      basename_of_dotfile=$(basename $name_of_dot_file)
      echo "Basename of dotfile: $basename_of_dotfile"
      echo "Moving $name_of_dot_file to $new_file_path";
      mv $name_of_dot_file $new_file_path;
      echo "Symlinking file $new_file_path to $name_of_dot_file ";
      ln -s $new_file_path  $name_of_dot_file;
  # Enable touchpad
  function qq__touchpad_enable(){
      xinput set-prop $(xinput | grep Touch | grep -Po 'id=\K[0-9]+')  "Device Enabled" 1
  # Set monitor highlighting 
  alias qq_set_higlighting_to_level_1_100="sudo xbacklight -set"
  # Display wifi SSID's
  alias qqwifi-spots="sudo iwlist scan | grep ESSID"
  # Add wifi network 
  function qqadd-wifi-network(){
      ## add-wifi-network just_wifi mypassword
      wpa_passphrase $1 $2 >> /etc/wpa_supplicant/wpa_supplicant.conf
  # Various, misc
  # Mirror (webcam)
  alias mirror="vlc v4l2:///dev/video0"
  # Stopwatch/countdown
  function stopwatch(){
    date1=`date +%s`; 
     while true; do 
      echo -ne "$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r"; 
      sleep 0.1
  function countdown(){
     date1=$((`date +%s` + $1)); 
     while [ "$date1" -ge `date +%s` ]; do 
       echo -ne "$(date -u --date @$(($date1 - `date +%s`)) +%H:%M:%S)\r";
       sleep 0.1
Some other stuff that I use daily and is too long to list here is:

  * an increment, deduplicating backup that takes
    around $0.52 per month on BackBlaze and on the 
    external hard drive via one command. 
    (Shameless plug: https://github.com/MichaelLeachim/borg_backblaze_backup)
  * Internet blocker.  (https://github.com/MichaelLeachim/internet_block)

Edit, formatting.

Cool, I like the qq-tar-gz-it, but I changed it to this:

function qq-tar-gz-it () { tar -zcvf ${1}.tar.gz $1; }

Saves a step.

use parallel compression/decompression

  alias bzip2='pbzip2'
  alias bunzip2='pbzip2 -d'
  alias gzip='pigz'
  alias gunzip='pigz -d'
  alias xz='pixz'
  alias tar='tar --use-compress-program=pbzip2'
  alias tar='tar --use-compress-program=pigz'

Determine external IP address alias ipget='dig +short myip.opendns.com @resolver1.opendns.com'

#simple and saves me a lot of time

gpush(){ git add --all . && git commit -m $1 && git push origin $2 }

    alias o=xdg-open
    alias dus='du -sh * | sort -h'
    alias mkae=make

for the `mkae` you should really use `thefuck` cli anti-typo tool ;) https://github.com/nvbn/thefuck

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact