#!/usr/bin/env bash # Create a new directory and enter it. function mkd() { mkdir -p "$@" && cd "$_"; } # find shorthand. function f() { find . -name "$1" 2>&1 | grep -v 'Permission denied' } # Change working directory to the top-most Finder window location. function cdf() { # short for `cdfinder` cd "$(osascript -e 'tell app "Finder" to POSIX path of (insertion location as alias)')"; } # Change working directory and then list contents. function cdl() { cd "$@" && ll; } # Create a .tar.gz archive, using `zopfli`, `pigz` or `gzip` for compression. function targz() { local tmpFile="${@%/}.tar"; tar -cvf "${tmpFile}" --exclude=".DS_Store" "${@}" || return 1; size=$( stat -f"%z" "${tmpFile}" 2> /dev/null; # macOS `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 ($((size / 1000)) kB) using \`${cmd}\`…"; "${cmd}" -v "${tmpFile}" || return 1; [ -f "${tmpFile}" ] && rm "${tmpFile}"; zippedSize=$( stat -f"%z" "${tmpFile}.gz" 2> /dev/null; # macOS `stat` stat -c"%s" "${tmpFile}.gz" 2> /dev/null; # GNU `stat` ); echo "${tmpFile}.gz ($((zippedSize / 1000)) kB) created successfully."; } # Determine size of a file or total size of a directory. function 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; } # Use Git’s colored diff when available. hash git &>/dev/null; if [ $? -eq 0 ]; then function diff() { git diff --no-index --color-words "$@"; } fi; # Create a data URL from a file. function 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')"; } # Start an HTTP server from a directory, optionally specifying the port. function 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"; } # The Life of a Web Developer. function lsoft() { local port="${1:-3000}"; lsof -i tcp:${port} } # Start a PHP server from a directory, optionally specifying the port. # (Requires PHP 5.4.0+.) function phpserver() { local port="${1:-4000}"; local ip=$(ipconfig getifaddr en1); sleep 1 && open "http://${ip}:${port}/" & php -S "${ip}:${port}"; } # Compare original and gzipped file size. function 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` function json() { if [ -t 0 ]; then # argument python -mjson.tool <<< "$*" | pygmentize -l javascript; else # pipe python -mjson.tool | pygmentize -l javascript; fi; } function localip(){ function _localip(){ echo "📶 "$(ipconfig getifaddr "$1"); } export -f _localip local purple="\x1B\[35m" reset="\x1B\[m" networksetup -listallhardwareports | \ sed -r "s/Hardware Port: (.*)/${purple}\1${reset}/g" | \ sed -r "s/Device: (en.*)$/_localip \1/e" | \ sed -r "s/Ethernet Address:/📘 /g" | \ sed -r "s/(VLAN Configurations)|==*//g" } # Run `dig` and display the most useful info. function digga() { dig +nocmd "$1" any +multiline +noall +answer; } # UTF-8-encode a string of Unicode symbols. function 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; } # whois a domain or a URL function whois() { local domain=$(echo "$1" | awk -F/ '{print $3}'); # get domain from URL if [ -z $domain ] ; then domain=$1; fi; echo "Getting whois record for: $domain …"; # avoid recursion # this is the best whois server # strip extra fluff /usr/bin/whois -h whois.internic.net $domain | sed '/NOTICE:/q'; } # Show all names (CNs and SANs) in SSL cert for a given domain. function 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" -servername "${domain}" 2>&1); if [[ "${tmp}" = *"-----BEGIN CERTIFICATE-----"* ]]; then local certText=$(echo "${tmp}" \ | openssl x509 -text -certopt "no_aux, no_header, no_issuer, no_pubkey, \ no_serial, no_sigdump, no_signame, no_validity, no_version"); echo "Common Name:"; echo ""; # newline echo "${certText}" | grep "Subject:" | sed -e "s/^.*CN=//" | sed -e "s/\/emailAddress=.*//"; 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; } # `st` with no arguments opens the current directory in VSCode, # otherwise opens the given location. function vs() { if [ $# -eq 0 ]; then open -a "Visual Studio Code" .; else open -a "Visual Studio Code" $@; fi; } # `v` with no arguments opens the current directory in Vim, # otherwise opens the given location. function v() { if [ $# -eq 0 ]; then vim .; else vim "$@"; fi; } # `o` with no arguments opens the current directory, # otherwise opens the given location. function o() { if [ $# -eq 0 ]; then open .; else open "$@"; 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. function tre() { tree -aC -I '.git|node_modules|bower_components' --dirsfirst "$@" | less -FRNX; } # preview csv files. source: http://stackoverflow.com/questions/1875305/command-line-csv-viewer function csvpreview(){ sed 's/,,/, ,/g;s/,,/, ,/g' "$@" | column -s, -t | less -#2 -N -S; } # $ aes-enc file.zip function aes-enc() { openssl enc -aes-256-cbc -e -in $1 -out "$1.aes" } # $ aes-dec file.zip.aes function aes-dec() { openssl enc -aes-256-cbc -d -in $1 -out "${1%.*}" } # Extract archives - use: extract # Based on http://dotfiles.org/~pseup/.bashrc function extract() { if [ -f "$1" ] ; then local filename=$(basename "$1") local foldername="${filename%%.*}" local fullpath=`perl -e 'use Cwd "abs_path";print abs_path(shift)' "$1"` local didfolderexist=false if [ -d "$foldername" ]; then didfolderexist=true read -p "$foldername already exists, do you want to overwrite it? (y/n) " -n 1 echo if [[ $REPLY =~ ^[Nn]$ ]]; then return fi fi mkdir -p "$foldername" && cd "$foldername" case $1 in *.tar.bz2) tar xjf "$fullpath" ;; *.tar.gz) tar xzf "$fullpath" ;; *.tar.xz) tar Jxvf "$fullpath" ;; *.tar.Z) tar xzf "$fullpath" ;; *.tar) tar xf "$fullpath" ;; *.taz) tar xzf "$fullpath" ;; *.tb2) tar xjf "$fullpath" ;; *.tbz) tar xjf "$fullpath" ;; *.tbz2) tar xjf "$fullpath" ;; *.tgz) tar xzf "$fullpath" ;; *.txz) tar Jxvf "$fullpath" ;; *.zip) unzip "$fullpath" ;; *) echo "'$1' cannot be extracted via extract()" && cd .. && ! $didfolderexist && rm -r "$foldername" ;; esac else echo "'$1' is not a valid file" fi } # npm-diff web-vitals-element 1.0.0 1.0.1 function npm-diff() { npm diff --diff=$1@$2 --diff=$1@$3 | delta --width $(tput cols) | less }