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!
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.
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()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
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.
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.)
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..
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
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.
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.)
alias crontab='fuck you, <insert name of colleague here>'
Background:
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.
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'
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:
# 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 }
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.
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.
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).
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.
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/)
fi
#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 "$@"
}
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
}
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
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"
}
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'
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"
Golang:
alias gopath='cd $GOPATH/src && tree -dL 3'
Git:
# --no-pager is underrated
alias glnp="git --no-pager log --oneline -n30"
Misc:
# 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'
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
}
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.
The default password length is 13 characters but you can pass a different length parameter instead.
Explanation:
* 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 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
cd_history[0]=$PWD
if [[ $1 == -h ]]; then
for i in ${!cd_history[@]}; do
echo $i: "${cd_history[$i]}"
done
return
elif [[ $1 =~ ^-[0-9]+ ]]; then
builtin cd "${cd_history[${1//-}]}" || # Remove the argument's dash
return
else
builtin cd "$@" || return # Bail if cd fails
fi
# 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.
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
HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups
_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
_bash_history_sync
builtin history "$@"
}
PROMPT_COMMAND=_bash_history_sync
Sometimes I forget the name of git branches I've worked on lately. This displays them with dates, most recent at the bottom:
# 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\]\$ "
.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.
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.
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' &&
tab-color-devil-blue"
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:
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.
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.
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.
(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.
# 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 {
NAM=""
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 ""
else
echo -e "Expected: fgr <search> [file filter] [grep opt]\n"
fi
}
A well crafted $CDPATH helps me jump from project to project and from directory to directory within a project without having to type many ../:
CDPATH=./:~/:~/Documents/:[...]
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 '127.0.0.1' | \awk '{print $2}' | \tr '\n' '-' | \sed 's/-.*//' | \tr -d '\n'
\exit 0
fi
# Linux
if [ "$SYSTEM" = "LINUX" ]; then
\ip route get 1 | \awk '{print $NF}' | \tr -d '\n'
\exit 0
fi
# MINGW/CYGWIN on Windows
if [ "$SYSTEM" = "MINGW" -o "$SYSTEM" = "CYGWI" ]; then
\ipconfig | \grep 'IPv4' | \awk '{print $NF}' | \tr -d '\n'
\exit 0
fi
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!
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.
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
fpath=$HOME/notes.md
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"
else
{
echo ''
echo "$@"
echo ''
} >>"$fpath"
fi
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)
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 "$*" ]
then
cd "$(dirname "$*")"
else
cd "$*"
fi
}
Also cwd which is like pwd but it also copies the current path to your clipboard.
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
for i in `ls ~/.ssh/keys|grep -v ".pub"|grep -v "id_dsa$"`; do
cmd="$i"ssh
func="function $cmd {"
func="$func ssh -i ~/.ssh/keys/$i \$*;"
func="$func }"
eval $func
done
}
_dynamic_ssh_creator
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.
# 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
else
echo "Makefile not found"
fi
}
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 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:
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
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
echo
# check if inside git repository
if git rev-parse --git-dir > /dev/null 2>&1 ; then
# if so, execute `git status'
git status
else
# else run `ls'
ls -l
fi
fi
# 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.
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
then
echo "No arguments (0_0)?"
elif test "$#" -eq 1
then
git add -u && git commit -m "$(echo $1 | sed 's/^./\U&\E/')"
else
git add ${@:1:$(( $# - 1 ))} && git commit -m "$(echo ${@:$#} | sed 's/^./\U&\E/')"
fi
}
Usage:
# 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"
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 () {
LOC="$1"
cd "${HOME}/work/$LOC"
tmux attach -dt "$LOC" || tmux new -s "$LOC"
}
Handle the git submodules nightmare (a little) more easily
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"
fi
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:
rcbash='~/.bashrc'
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])+$ ]]
then
return 0 # true = 0
else
return 1 # false = 1
fi
}
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)
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).
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:
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:
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:
errno$
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.
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'"
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"
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.
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"
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.
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 $@
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:
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 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
fi
local host_port="$1"
if [[ "$1" != *:* ]]; then
local host_port="${1}:443"
fi
openssl s_client -connect "${host_port}" </dev/null 2>/dev/null | grep -E '\ (s|i):'
}
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 ../
up(){
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^\///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}
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
#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"
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"
or
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.
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!)
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...
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
-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.
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.
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.
function age () {
NAME="$1";
DATE="$2";
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 /';
else
echo "No name or date supplied";
fi
}
function child () {
age "My child" "2012-03-12";
}
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.
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(){
directory_for_dot_file=$2
name_of_dot_file=$1
basename_of_dotfile=$(basename $name_of_dot_file)
echo "Basename of dotfile: $basename_of_dotfile"
dot_file_with_striped_dot=${basename_of_dotfile:1}
new_file_path=$directory_for_dot_file/$dot_file_with_striped_dot
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
done
}
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
done
}
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)
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'
#~/.inputrc is for nerds who don't want 1000-line bashrcs
#C-w deletes previous word (by spaces) by default
#bind C-q to delete previous word-segment instead of "start(?) term output"
stty -ixon
bind '"\C-q": backward-kill-word'
#bind C-s to move cursor to previous [:space:] instead of "stop(?) term output"
bind -r '\C-s'
bind '"\C-s": shell-backward-word'
#bind C-d to go forword, not crush the shell
set -o ignoreeof
bind '"\C-d": shell-forward-word'
#miscellaneous useful inputrc binds
#bind shift-tab to 'see how the next autocomplete option would look on the cmd line'
bind '"\e[Z": menu-complete'
#don't make me hit tab twice to see multiple completion options
bind "set show-all-if-ambiguous on"
bind "set show-all-if-unmodified on"
#multi-complete shows filetypes by colors
bind "set colored-stats on"
#ellipsis at 3+ common characters with multi-complete
bind "set completion-prefix-display-length 3"
if [[ "$__os" == "mac" ]]; then
#tab complete is no longer case-sensitive? interesting...
bind "set completion-ignore-case on"
#tab complete is not -_ sensitive.
bind "set completion-map-case on"
fi
#vim mode is actually a super pain compared to emacs on the command line.
set -o emacs
#C-n/p now do double duty, so this is like the best of all 3 worlds? I'll take it
bind '"\C-p":history-search-backward'
bind '"\C-n":history-search-forward'
#makes aliases work with sudo
alias sudo='sudo '
#use sudo -i to become root and keep your bashrc & vimrc
alias -- -i='-E bash --rcfile $HOME/.bashrc'
#can't get it to work when becoming other users. sucks to suck.
alias apt-get='sudo apt-get'
alias systemctl='sudo systemctl'
alias sc='sudo systemctl'
alias scr='sudo systemctl restart'
alias firewall='sudo firewall-cmd'
alias fw='sudo firewall-cmd'
alias yum='sudo yum'
alias yumy='sudo yum install -y'
alias py='python'
# b/c sed needs i with an empty string on Mac to properly in-place
alias sd='sed -i"" -e'
#alias ugh = sudo !!
alias ugh='sudo $(history -p !!)'
# -a: dotfiles. -I: not those dotfiles. -C: color.
alias tree='tree -a -C -I ".git"'
#tries to force color: (G):BSD; (--color):GNU, adds / after dirs, * after execs, etc (F);
#and human readable sizes (h)
alias ls='ls --color -GFh'
alias la='ls --color -GFhla'
alias cd.='cd ../'
alias cd..='cd ../../'
alias cd...='cd ../../../'
alias cd....='cd ../../../../'
#is it running? sometimes you need all the args (i.e., for java processes) to fully grep
psg() {
ps -ef | grep -i $* | grep -v grep || \
ps -efwww | grep -i $* | grep -v grep
}
alias g.='grep '\''.'\'' -IrnHe'
alias f.='find . -name'
I use these functions a lot: down and up. They're quite useful for navigating big source trees where stuff isn't well laid-out but you don't remember exact paths.
They work kind of like z/j, but you don't have to have been there before and it will constrain to the current tree.
down SUB1 SUB2[...] does a breadth-first search down-tree from your current location, and takes you to the first directory with all the given substrings in order in its path.
This differs from just wrapping basic find . -ipath, which does depth-first. That way, down libs lands you in ./src/libs instead of ./src/a_subcomponent/foo/bar/libs.
up SUB1 does the same, but moves you up the tree instead. I didn't do multiple substrings here because I never needed them--I mostly use them with down to anchor to a subtree (e.g., down a_sub libs if I wanted the above result).
Both are case-insensitive as written. Change ipath to path in down and grep -oi to grep -o in up to make them case sensitive instead.
They may or may not be symlink safe, and may or may not be spaces-in-paths safe. Neither is in play in my source bases.
Last note, these were originally written in fish (ask me for those versions if you want them) before I ported them to bash, so may not be examples of stunning bash code. They've been tested on bash 3.2 (Mac), 4.x, and 5.0.
function joinstr {
local IFS="$1"
shift;
echo "$*"
}
function down {
if [ -z "$1" ]; then
echo "Usage: down SUBSTR [SUBSTR...]"
return 1
fi
# foo bar baz becomes *foo*bar*baz*
local pathspec=( "$@" )
pathspec="*"$(joinstr "*" ${pathspec[@]})"*"
local depth=1
local dest=""
# iterative depth first traversal to simulate breadth-first
while true; do
# Anything at all at this depth?
local first_result=$(find . -mindepth "${depth}" -maxdepth "${depth}" -type d -print -quit)
if [ -z "${first_result}" ]; then
# nope, we're done
break
fi
# How about what we're looking for?
dest=$(find . -mindepth "${depth}" -maxdepth "${depth}" -ipath "${pathspec}" -type d -print -quit)
if [ -n "${dest}" ]; then
# found it!
break
fi
depth=$((${depth} + 1))
done
if [ -z "${dest}" ]; then
echo "down: could not find path matching ${pathspec}"
return 2
fi
echo "down: changing directory to ${dest}"
cd "${dest}"
}
function up {
if [ -z "$1" -o -n "$2" ]; then
echo "Usage: up SUBSTR"
return 1
fi
# look for substr starting at parent
local dest=$(echo ${PWD%/*} | grep -oi ".*$1[^/]*")
if [ -z "${dest}" ]; then
echo "up: could not find path matching *$1*"
return 2
fi
echo "up: changing directory to ${dest}"
cd "${dest}"
}
I have the below for cases when I have to make a quick screencast. It needs ffmpeg and I am not sure how well the yt flag works as I don't really use Youtube any longer. Anyway.. first I do 'ffsc sc' and if I want that video to be smaller I do 'ffsc yt <path_to_file>'.
Truncate the $PWD to ¼ of the terminal width and put the result into the command prompt:
# truncate the $PWD
function cut_pwd
{
newPWD="${PWD/#$HOME/\~}"
local pwdmaxlen=$((${COLUMNS:-80}/4))
if [ ${#newPWD} -gt $pwdmaxlen ]
then
newPWD=".+${newPWD: -$pwdmaxlen}"
fi
}
PROMPT_COMMAND=cut_pwd
PS1="\h:\${newPWD} \\$ "