Title: Aliases and helper functions for the shell Author: paco Date: 2020-07-03 Type: article This is a compilation of shell aliases and helper functions I found useful and use more or less regularly. Some of them are of my creation and some have been stolen and adapted over the years. It's not a complete list. Just the ones that I think might be useful to somebody else. This comes from a [toot from pamela@][1], and I thought to put it here to be more permanent. I use `zsh` on my machines as interactive shell, but I guess this can be used with little to no modification on other shells. I also use `tmux(1)` heavily. ## Basic aliases First some basic aliases (comments in line): ``` # create a tmux split 82 columns wide, used to take a peek at man pages alias tman='tmux split-window -h -l 82 man' ``` _Update 2021-05-01:_ Reader Chang, Chu-Kuan sends me a variation of this last one that does not require you to have a _free_ terminal to invoke it. It's basically the same but with a `tmux(1)` bind key. This should go in your `.tmux.conf`: ``` bind-key M command-prompt -I 'split-window -h -l 82 man ' ``` And now, more aliases: ``` # I use kubernetes at work, so those save a lot of typing. # I also use some custom subcommands, via kubectl plugins. I might write about # that ... if command -v kubectl > /dev/null ; then alias k='kubectl' alias kg='kubectl get' alias kgdep='kubectl get deployment' alias kgsvc='kubectl get service' alias kging='kubectl get ingress' alias kgcm='kubectl get configmap' alias kgsec='kubectl get secret' alias kd='kubectl describe' alias ka='kubectl apply -f' alias krm='kubectl delete' alias kex='kubectl exec -i -t' alias kedep='kubectl edit deployment' alias kecm='kubectl edit configmap' alias ktopn='kubectl top node' fi # also for work, google cloud sdk stuff ... if command -v gcloud > /dev/null ; then alias gcil='gcloud compute instances list' alias gcssh='TERM=screen-256color gcloud compute ssh' alias gcscp='gcloud compute scp' # those 2 are specially useful, to sync the context change # for Google cloud project and kubernetes cluster alias Sprod='kubectl config use-context prod; gcloud config configurations activate prod' alias Sstg='kubectl config use-context stg; gcloud config configurations activate default' fi # I always forget to use doas with pkg_* commands. Also, set -Dsnap which # never hurts if command -v pkg_add > /dev/null; then for c in add delete check; do alias pkg_${c}="doas /usr/sbin/pkg_${c} -Dsnap" done alias pkg_info="/usr/sbin/pkg_info -Dsnap" fi ``` ## Named directories I also make some heavy use of named directories in `zsh`. This is probably not present on other shells. The thing is that I can refer to common used folders by a short name, like `~se` for `$HOME/src/git.e1e0.net` and things like that. And they work anywhere on the command line. Here some examples: ``` test -d $HOME/src && hash -d s=$HOME/src test -d $HOME/src/git.e1e0.net && hash -d se=$HOME/src/git.e1e0.net test -d /mnt/nas/fotos && hash -d f=/mnt/nas/fotos ... ``` ## Helper functions The next bits are for interacting with my [transmission][2] server at home. I never remember the options and stuff, so this covers the basic operations: ``` # list torrents alias trls='transmission-remote my.transmission.host --authenv -l' # remove a torrent from the list (-d deletes the downloaded files too) function trrm () { if [[ "$1" == "-d" ]]; then action="--remove-and-delete" torrent="$2" else action="--remove" torrent="$1" fi transmission-remote my.transmission.host --authenv -t $torrent $action } # clean all torrents from the queue function trclean() { for i in $(transmission-remote my.transmission.host --authenv -l | awk '$2=="100%" {print $1}') do if [[ "$1" == "-d" ]]; then action="--remove-and-delete" else action="--remove" fi transmission-remote my.transmission.host --authenv -t $i $action done } ``` For adding torrents I use a python script so I can put them more or less automatically in folders to organize them, but that's a bit more complicated. Some temperature conversion helpers (not used every day, but nice to have): ``` # temperature conversion function c2f() { F=$(printf "scale=2\n$1 * 1.80 + 32\n" | bc) printf "C: $1\nF: $F\n" } function f2c() { C=$(printf "scale=2\n($1 -32)/1.80\n" | bc) printf "F: $1\nC: $C\n" } # for everything else, use units(1) ``` This one is pretty useful, as my ISP changes my public IP regularly. ``` # What is my External IP function myip() { printf "External IP: %s\n" $(curl -s -4 http://ifconfig.co/) ;} ``` Small random ones (commented in place): ``` # quick and dirty file backup. function bak() { cp -v ${1}{,.bak} } # replace all spaces by underscore (only for zsh) function mvsp() { autoload -U zmv zmv '* *' '$f:gs/ /_' } # Grep the history with 'h' function h () { if command -v rg > /dev/null 2>&1 then mycommand=rg else mycommand=grep fi history 0 | $mycommand $1 } # weather forecast on the terminal. Just fantastic. function wf () { CITY=$1 if [[ -z "$CITY" ]]; then CITY="MyCity" fi curl wttr.in/${CITY} } # function to copy main ssh keys to clipboard when needed. function pubkey () { ssh-add -L |grep 'cardno:000000000000' |\ xclip -f -selection clipboard echo "=> Public key copied to clipboard." } # Neat trick from https://github.com/lf94/peek-for-tmux/blob/master/README.md # temporary tmux split (1/3 of the window) to look into some file function peek() { tmux split-window -p 33 less $@ || exit; } ``` This one I use quite a bit. It's my personal _pastebin_: ``` # poor man's pastebin service (and secure !) function pb() { filename="$1" dest="" if [[ -z "$filename" ]]; then dest=$(tr -cd '[:alnum:]' < /dev/urandom |dd bs=1 count=8 2>/dev/null) ssh w1.e1e0.net "cat > /var/www/pastes/$dest" else dest=$(basename "$filename") scp -q "$filename" "w1.e1e0.net:/var/www/pastes/$dest" fi echo -n "https://e1e0.net/paste/$dest" |\ xclip -f -selection clipboard echo '' } ``` It can be used like `echo foo | pb` or `pb myfile.txt` and will produce a unique URL if no file name is provided. And a shortcut and dispatcher for `git`. `g` executes `git status -s` and everything else is just passed to `git` as is. ``` function g() { if (( $# == 0 )); then git status -s else git "$@" fi } ``` ## OpenBSD ports stuff. And now the ports stuff. All this is probably overkill, but I use them all the time while working with ports. As the comment at the top says this is totally stolen from other devs. I can't remember what's from who, I probably took bits and pieces from their public dot files and just adapted it to my needs. Basically this is a dispatcher function `p`. It composes the name of the function to call. If it exists it's called, if not the `_port-doas` function is called. This is useful as I use `PORTS_PRIVSEP=Yes` so everything in ports belongs to the user `_pbuild`. Some functions make use of external commands like _danj@_'s `show-victims` (this is actually a rewrite I did in Go, the original in Python) to look for consumers of a port, or _juanfra@_'s `outdated-packages.py` to query [portroach][3]. The latter is pretty useful for _"port fishing"_. Remember folks, there are a lot of outdated ports without maintainer ! ``` # ports stuff # shamelessly stolen from Klemens Nanni (kn@), Daniel Jakots (danj@) # and Solene Rapenne (solene@) p() { [ $# -gt 0 ] || return if typeset -f \_port-"$1" > /dev/null; then _port-"$@" else _port-doas "$@" fi } function _port-search() { local pt="/usr/ports" [[ -z ${1} ]] && echo "Need a keyword to search for" && return [[ ! -d ${pt} ]] && echo "Cannot find ports tree" && return cd ${pt} && make search name=${1} cd - } function _port-s() { \_port-search "$@" } function _port-sql() { sqlite3 /usr/local/share/sqlports } function _port-pldc() { make port-lib-depends-check } function _port-ldc() { make lib-depends-check } function _port-pdf() { if command -v cdiff > /dev/null ; then diff -up pkg/PLIST.orig pkg/PLIST | cdiff else diff -up pkg/PLIST.orig pkg/PLIST | less fi } function _port-src() { cd `make show=WRKSRC` } function _port-clean() { make clean=all } function _port-diff() { if [[ -d /usr/ports/.got/ ]]; then got diff > /usr/ports/mystuff/${PWD##*/}.diff else cvs diff > /usr/ports/mystuff/${PWD##*/}.diff fi if command -v cdiff > /dev/null ; then cdiff /usr/ports/mystuff/${PWD##*/}.diff else less /usr/ports/mystuff/${PWD##*/}.diff fi } function _port-df() { \_port-diff "$@" } function _port-lessdiff() { if command -v cdiff > /dev/null ; then cdiff /usr/ports/mystuff/${PWD##*/}.diff else less /usr/ports/mystuff/${PWD##*/}.diff fi } function _port-ldf() { \_port-lessdiff "$@" } function _port-pygrep() { rg $@ --type make --glob '!*mystuff*' --glob '!lost+found' /usr/ports/*/py-* } function _port-f() { \_port-find "$@" } function _port-find() { rg -i $@ /usr/local/share/sqlports.list } function _port-grep() { rg $@ --type make --glob '!*mystuff*' --glob '!lost+found' /usr/ports } function _port-update() { local current_dir=$(pwd) if [[ -d /usr/ports/.got ]]; then cd /var/git/ports.git/ && git fetch origin master:master cd /usr/ports && got update -b master cd "$current_dir" else cd /usr/ports && cvs -q up -Pd -A && cd "$current_dir" fi } function _port-up() { \_port-update "$@" } function _port-lessmake() { less "/usr/ports/$1/Makefile" } function _port-lmk() { \_port-lessmake "$@" } function _port-doas() { command doas -u _pbuild "$@" } function _port-help() { # (k) returns only the keys from associative array. Look zshexpn(1) printf "%s\n" "${(k)functions[@]}" | sort | grep "^_port-" | sed 's/_port-//' } function _port-ou() { \_port-outdated "$@" } function _port-outdated() { if [ ! -x "$HOME/bin/outdated-packages.py" ]; then echo "Cannot find script" >&2 && return fi "$HOME/bin/outdated-packages.py" "$@" } function _port-sv() { \_port-showvictims "$@" } function _port-showvictims() { if [ ! -x "$HOME/bin/port-showvictims" ]; then echo "Cannot find executable" >&2 && return fi "$HOME/bin/port-showvictims" "$@" } function _port-patch { local level=${2:-0} patch -E -C -p$level < $1 && patch -E -p$level < $1 echo $? } alias py3='env FLAVOR=python3 ' function cvsdiff() { if command -v cdiff > /dev/null ; then cvs diff $@ | cdiff else cvs diff $@ | less fi } ``` And that's basically it. I hope is useful for somebody. [1]: https://bsd.network/@pamela/104370718366426100 [2]: https://transmissionbt.com/ [3]: https://portroach.openbsd.org/