#!/bin/bash # Trap RC != 0 and display EC() { echo -e '\e[1;31m'code $?'\e[m\n' } trap EC ERR # Simple calculator calc() { local result="" result="$(printf "scale=10;$*\n" | bc --mathlib | tr -d '\\\n')" # └─ default (when `--mathlib` is used) is 20 if [[ "$result" == *.* ]]; then # improve the output for decimal numbers printf "$result" | sed -e 's/^\./0./' `# add "0" for cases like ".5"` \ -e 's/^-\./-0./' `# add "0" for cases like "-.5"`\ -e 's/0*$//;s/\.$//'; # remove trailing zeros else printf "$result" fi printf "\n" } # Create a new directory and enter it mkd() { mkdir -p "$@" && cd "$@" } # cd and list cl() { local dir="$1" local dir="${dir:=$HOME}" if [[ -d "$dir" ]]; then cd "$dir" >/dev/null; ls -l else echo "bash: cl: $dir: Directory not found" fi } # Simple Note App note () { # if file doesn't exist, create it if [[ ! -f $HOME/.notes ]]; then touch "$HOME/.notes" fi if ! (($#)); then # no arguments, print file cat "$HOME/.notes" elif [[ "$1" == "-c" ]]; then # clear file printf "%s" > "$HOME/.notes" else # add all arguments to file printf "%s\n" "$*" >> "$HOME/.notes" fi } todo() { if [[ ! -f $HOME/.todo ]]; then touch "$HOME/.todo" fi if ! (($#)); then cat "$HOME/.todo" elif [[ "$1" == "-l" ]]; then nl -b a "$HOME/.todo" elif [[ "$1" == "-c" ]]; then > $HOME/.todo elif [[ "$1" == "-r" ]]; then nl -b a "$HOME/.todo" eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo read -p "Type a number to remove: " number sed -i ${number}d $HOME/.todo else printf "%s\n" "$*" >> "$HOME/.todo" fi } # Make a temporary directory and enter it tmpd() { if [ $# -eq 0 ]; then dir=`mktemp -d` && cd $dir else dir=`mktemp -d -t $1.XXXXXXXXXX` && cd $dir fi } # Create a .tar.gz archive, using `zopfli`, `pigz` or `gzip` for compression targz() { local tmpFile="${@%/}.tar" tar -cvf "${tmpFile}" --exclude=".DS_Store" "${@}" || return 1 size=$( stat -f"%z" "${tmpFile}" 2> /dev/null; # OS X `stat` stat -c"%s" "${tmpFile}" 2> /dev/null # GNU `stat` ) local cmd="" if (( size < 52428800 )) && hash zopfli 2> /dev/null; then # the .tar file is smaller than 50 MB and Zopfli is available; use it cmd="zopfli" else if hash pigz 2> /dev/null; then cmd="pigz" else cmd="gzip" fi fi echo "Compressing .tar using \`${cmd}\`…" "${cmd}" -v "${tmpFile}" || return 1 [ -f "${tmpFile}" ] && rm "${tmpFile}" echo "${tmpFile}.gz created successfully." } # Determine size of a file or total size of a directory fs() { if du -b /dev/null > /dev/null 2>&1; then local arg=-sbh else local arg=-sh fi if [[ -n "$@" ]]; then du $arg -- "$@" else du $arg .[^.]* * fi } # Create a data URL from a file dataurl() { local mimeType=$(file -b --mime-type "$1") if [[ $mimeType == text/* ]]; then mimeType="${mimeType};charset=utf-8" fi echo "data:${mimeType};base64,$(openssl base64 -in "$1" | tr -d '\n')" } # Create a git.io short URL gitio() { if [ -z "${1}" -o -z "${2}" ]; then echo "Usage: \`gitio slug url\`" return 1 fi curl -i http://git.io/ -F "url=${2}" -F "code=${1}" } # Start an HTTP server from a directory, optionally specifying the port server() { local port="${1:-8000}" sleep 1 && open "http://localhost:${port}/" & # Set the default Content-Type to `text/plain` instead of `application/octet-stream` # And serve everything as UTF-8 (although not technically correct, this doesn’t break anything for binary files) python -c $'import SimpleHTTPServer;\nmap = SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map;\nmap[""] = "text/plain";\nfor key, value in map.items():\n\tmap[key] = value + ";charset=UTF-8";\nSimpleHTTPServer.test();' "$port" } # Compare original and gzipped file size gz() { local origsize=$(wc -c < "$1") local gzipsize=$(gzip -c "$1" | wc -c) local ratio=$(echo "$gzipsize * 100 / $origsize" | bc -l) printf "orig: %d bytes\n" "$origsize" printf "gzip: %d bytes (%2.2f%%)\n" "$gzipsize" "$ratio" } # Syntax-highlight JSON strings or files # Usage: `json '{"foo":42}'` or `echo '{"foo":42}' | json` json() { if [ -t 0 ]; then # argument python -mjson.tool <<< "$*" | pygmentize -l javascript else # pipe python -mjson.tool | pygmentize -l javascript fi } # Run `dig` and display the most useful info digga() { dig +nocmd "$1" any +multiline +noall +answer } # UTF-8-encode a string of Unicode symbols escape() { printf "\\\x%s" $(printf "$@" | xxd -p -c1 -u) # print a newline unless we’re piping the output to another program if [ -t 1 ]; then echo ""; # newline fi } # Decode \x{ABCD}-style Unicode escape sequences unidecode() { perl -e "binmode(STDOUT, ':utf8'); print \"$@\"" # print a newline unless we’re piping the output to another program if [ -t 1 ]; then echo ""; # newline fi } # Get a character’s Unicode code point codepoint() { perl -e "use utf8; print sprintf('U+%04X', ord(\"$@\"))" # print a newline unless we’re piping the output to another program if [ -t 1 ]; then echo ""; # newline fi } # Show all the names (CNs and SANs) listed in the SSL certificate # for a given domain getcertnames() { if [ -z "${1}" ]; then echo "ERROR: No domain specified." return 1 fi local domain="${1}" echo "Testing ${domain}…" echo ""; # newline local tmp=$(echo -e "GET / HTTP/1.0\nEOT" \ | openssl s_client -connect "${domain}:443" 2>&1) if [[ "${tmp}" = *"-----BEGIN CERTIFICATE-----"* ]]; then local certText=$(echo "${tmp}" \ | openssl x509 -text -certopt "no_header, no_serial, no_version, \ no_signame, no_validity, no_issuer, no_pubkey, no_sigdump, no_aux") echo "Common Name:" echo ""; # newline echo "${certText}" | grep "Subject:" | sed -e "s/^.*CN=//" echo ""; # newline echo "Subject Alternative Name(s):" echo ""; # newline echo "${certText}" | grep -A 1 "Subject Alternative Name:" \ | sed -e "2s/DNS://g" -e "s/ //g" | tr "," "\n" | tail -n +2 return 0 else echo "ERROR: Certificate not found." return 1 fi } # `v` with no arguments opens the current directory in Vim, otherwise opens the # given location v() { if [ $# -eq 0 ]; then vim . else vim "$@" fi } # `o` with no arguments opens the current directory, otherwise opens the given # location o() { if [ $# -eq 0 ]; then xdg-open . > /dev/null 2>&1 else xdg-open "$@" > /dev/null 2>&1 fi } # `tre` is a shorthand for `tree` with hidden files and color enabled, ignoring # the `.git` directory, listing directories first. The output gets piped into # `less` with options to preserve color and line numbers, unless the output is # small enough for one screen. tre() { tree -aC -I '.git' --dirsfirst "$@" | less -FRNX } # Get colors in manual pages man() { env \ LESS_TERMCAP_mb=$(printf "\e[1;31m") \ LESS_TERMCAP_md=$(printf "\e[1;31m") \ LESS_TERMCAP_me=$(printf "\e[0m") \ LESS_TERMCAP_se=$(printf "\e[0m") \ LESS_TERMCAP_so=$(printf "\e[1;44;33m") \ LESS_TERMCAP_ue=$(printf "\e[0m") \ LESS_TERMCAP_us=$(printf "\e[1;32m") \ man "$@" } # Use feh to nicely view images openimage() { local types='*.jpg *.JPG *.png *.PNG *.gif *.GIF *.jpeg *.JPEG' cd $(dirname "$1") local file=$(basename "$1") feh -q $types --auto-zoom \ --sort filename --borderless \ --scale-down --draw-filename \ --image-bg black \ --start-at "$file" } # get dbus session dbs() { local t=$1 if [[ -z "$t" ]]; then local t="session" fi dbus-send --$t --dest=org.freedesktop.DBus \ --type=method_call --print-reply \ /org/freedesktop/DBus org.freedesktop.DBus.ListNames } # check if uri is up isup() { local uri=$1 if curl -s --head --request GET "$uri" | grep "200 OK" > /dev/null ; then notify-send --urgency=critical "$uri is down" else notify-send --urgency=low "$uri is up" fi } # get the name of a x window xname(){ local window_id=$1 if [[ -z $window_id ]]; then echo "Please specifiy a window id, you find this with 'xwininfo'" return 1 fi local match_string='".*"' local match_int='[0-9][0-9]*' local match_qstring='"[^"\\]*(\\.[^"\\]*)*"' # NOTE: Adds 1 backreference # get the name xprop -id $window_id | \ sed -nr \ -e "s/^WM_CLASS\(STRING\) = ($match_qstring), ($match_qstring)$/instance=\1\nclass=\3/p" \ -e "s/^WM_WINDOW_ROLE\(STRING\) = ($match_qstring)$/window_role=\1/p" \ -e "/^WM_NAME\(STRING\) = ($match_string)$/{s//title=\1/; h}" \ -e "/^_NET_WM_NAME\(UTF8_STRING\) = ($match_qstring)$/{s//title=\1/; h}" \ -e '${g; p}' } # Docker d_stop(){ docker stop $(docker ps -q) } d_clean(){ docker rm $(docker ps -q -f status=exited) docker rmi $(docker images -q -f dangling=true) docker volume rm $(docker volume ls -f dangling=true) } d_reset(){ docker stop $(docker ps -q) docker rm -f $(docker ps -aq) docker rmi -f $(docker images -qa) docker volume rm $(docker volume ls -q) } ## Radare2 Container OPS d_r2(){ docker run \ -ti --rm \ --cap-add=SYS_PTRACE \ --name r2 \ -v ~/RE:/mnt \ -v ~/.radare2rc:/home/r2/.radare2rc:ro \ -v ~/.bashrc:/home/r2/.bashrc:ro \ -v ~/.bash_profile:/home/r2/.bash_profile:ro \ -v ~/.exports:/home/r2/.exports:ro \ -v ~/.aliases:/home/r2/.aliases:ro \ radare/radare2 \ bash } d_r2s(){ docker exec -ti r2 bash } ## Menu-Man mman(){ man -k . | sort | dmenu -l 30 | awk '{print substr($2, 2, length($2) - 2) " " $1}' | xargs -r $TERMINAL -e man } ## Dump SSL Cert from host ## sslcheck example.com:25 -starttls smtp ## sslcheck example.com:443 sslcheck(){ echo -n | openssl s_client -connect $* | tee /dev/tty | openssl x509 -text -noout } ## kubesel: fzf-select a cubeconfig and source it kubesel(){ kubeconfig=$(find ~/.kube/kubesel -type f | rev | cut -d "/" -f 1 | rev | sort | fzf) export KUBECONFIG=~/.kube/kubesel/$kubeconfig } ## SSH agent ## Add sth like test -z $noKeychain && agent to ~/.extra function agent(){ /usr/bin/keychain --nolock --nogui $HOME/.ssh/id_rsa source $HOME/.keychain/$HOSTNAME-sh }