|
@@ -0,0 +1,454 @@
|
|
|
+#+title: .bashrc
|
|
|
+#+date: <2020-11-29 10:51:24 Sunday>
|
|
|
+#+author: George M Jones
|
|
|
+#+email: gmj@pobox.com
|
|
|
+#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:nil arch:headline
|
|
|
+#+options: author:t broken-links:nil c:nil creator:nil
|
|
|
+#+options: d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t num:2
|
|
|
+#+options: p:nil pri:nil prop:nil stat:t tags:t tasks:t tex:t
|
|
|
+#+options: timestamp:t title:t toc:t todo:t |:t
|
|
|
+#+language: en
|
|
|
+#+select_tags: export
|
|
|
+#+exclude_tags: noexport
|
|
|
+#+creator: Emacs 28.0.50 (Org mode 9.4)
|
|
|
+
|
|
|
+
|
|
|
+* About
|
|
|
+** Intro
|
|
|
+ This is George Jones' .bashrc file as an literate programming file in
|
|
|
+ emacs org mode using babel blocks.
|
|
|
+
|
|
|
+** To generate the actual .bashrc
|
|
|
+ This .bashrc.org file must be process to generate the actual .bashrc
|
|
|
+
|
|
|
+ It can be processed interactively to generate .bashrc via
|
|
|
+ org-babel-tangle-file or from the command line as
|
|
|
+
|
|
|
+ #+begin_example
|
|
|
+ emacs --batch --eval "(require 'org)" --eval '(org-babel-tangle-file ".bashrc.org")'
|
|
|
+ #+end_example
|
|
|
+
|
|
|
+ Permanent changes must be made to the .org version, as the actual
|
|
|
+ .bashrc will be overwritten when the .org version is "compiled"
|
|
|
+
|
|
|
+** Debugging
|
|
|
+
|
|
|
+ In most bash files I do
|
|
|
+
|
|
|
+ #+begin_example
|
|
|
+ set -e
|
|
|
+ set -u
|
|
|
+ #+end_example
|
|
|
+
|
|
|
+ but there are problems setting it in .bashrc. An error then causes
|
|
|
+ you to exit the shell entirely (not what you want), and there are
|
|
|
+ several constructs that cause warnings due to undefined variables
|
|
|
+ (these can/probably should be fixd)
|
|
|
+
|
|
|
+ Set
|
|
|
+
|
|
|
+ #+begin_example
|
|
|
+ export DEBUG=1
|
|
|
+ #+end_example
|
|
|
+
|
|
|
+ to enable debugging output from the debug helper function.
|
|
|
+
|
|
|
+* .bashrc
|
|
|
+** Helper functions
|
|
|
+ I define a few syslog-ish helper functions to print warnings,
|
|
|
+ errors, etc.
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ #PROG=`basename "$0" | tr -d '\n'` # normal setting
|
|
|
+ PROG="bashrc" # setting for bashrc due to errors
|
|
|
+
|
|
|
+ function info() { echo ${PROG}\: info: "$@" 1>&2; }
|
|
|
+ function warn() { echo ${PROG}\: warning: "$@" 1>&2; }
|
|
|
+ function error() { echo ${PROG}\: error: "$@" 1>&2; }
|
|
|
+ function debug() { [[ -v DEBUG ]] && echo ${PROG}\: debug: "$@" 1>&2 || true ; }
|
|
|
+ function die() { echo ${PROG}\: fatal: "$@" 1>&2 && exit 1; }
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Set a reasonable default prompt
|
|
|
+
|
|
|
+ Here I set a reasonable default prompt that includes timestamp,
|
|
|
+ username, host and current directory:
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+export PS1="\# [\t] \u@\h \W/ $ "
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Misc aliases
|
|
|
+
|
|
|
+ Define various aliases that I use
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ alias rm=' rm -i'
|
|
|
+ alias ag=' alias | grep -i'
|
|
|
+ alias eg=' printenv | grep -i'
|
|
|
+ alias hg=' history | grep -i'
|
|
|
+ alias ht=' history | tail'
|
|
|
+ alias fpg=' find . -print | egrep -i'
|
|
|
+ alias egi=' egrep -i'
|
|
|
+ alias psg=' /bin/ps -auxww | grep'
|
|
|
+ alias p8=' ping -c 3 8.8.8.8' # make sure routing works
|
|
|
+ alias pp=' ping -c 3 port111.com' # make sure dns and routing work
|
|
|
+ alias locate='locate -r'
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** cd commands that use/print the directory stack
|
|
|
+
|
|
|
+ These aliases support pushd/popd/dirs like functionality while
|
|
|
+ listing one directory per line
|
|
|
+
|
|
|
+ I like to keep a "stack" of directories so I can work on one thing
|
|
|
+ then "pop" back to where I was. =pushd= an =popd= support this,
|
|
|
+ and =dirs= lists the directories, but I prefer to have them listed
|
|
|
+ one per line.
|
|
|
+
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ function dirl() {
|
|
|
+ # "DIR"ectory "L"ist directory stack, one per line
|
|
|
+ # Usage: dirl
|
|
|
+
|
|
|
+ for d in `dirs`; do echo $d; done
|
|
|
+ }
|
|
|
+
|
|
|
+ function dirc() {
|
|
|
+ # "DIR"ectory "C"onnect - connect to directory and list stack
|
|
|
+ # Usage: dirc [DIR
|
|
|
+
|
|
|
+ pushd ${1:-"$HOME"} > /dev/null
|
|
|
+ dirl
|
|
|
+ }
|
|
|
+
|
|
|
+ function dirp () {
|
|
|
+ # "DIR"ectory "P"op - pop N entries off the directory stack
|
|
|
+ # Usage: dirp [N]
|
|
|
+ #
|
|
|
+ # OLD:
|
|
|
+ # alias dirp='popd > /dev/null && dirl'
|
|
|
+ for i in `seq ${1:-"1"}`; do
|
|
|
+ debug "dirl: popd. i is $i"
|
|
|
+ popd > /dev/null;
|
|
|
+ done
|
|
|
+ dirl
|
|
|
+ }
|
|
|
+
|
|
|
+ alias cd=pushd
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Misc functions
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+
|
|
|
+ function gf() {
|
|
|
+ # grep-find: grep for patterins in files via find
|
|
|
+ #
|
|
|
+ # Usage: gf patterns [files [days]]
|
|
|
+ #
|
|
|
+ # Examples:
|
|
|
+ # gf findMeAnywhere
|
|
|
+ # gf findMeInTextFiles '*.txt'
|
|
|
+ # gf findMeInTextFiles .txt
|
|
|
+ # gf BEGIN\|END .org 30
|
|
|
+
|
|
|
+ local files=""
|
|
|
+ local days="365"
|
|
|
+
|
|
|
+ set -o noglob
|
|
|
+
|
|
|
+ # First arg is pattern(s) for egrep
|
|
|
+ if [ -z ${1+x} ]; then
|
|
|
+ echo 'gf needs string(s) to search for ' 1>&2
|
|
|
+ info "Usage: gf patterns [files [days]]"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Second arg (if present) is files for find. No globbing, so "*.txt" OK
|
|
|
+ if [ ! -z ${2+x} ]; then
|
|
|
+ if [[ "$2" =~ ^\. ]]; then
|
|
|
+ # Special case: treat ".foo" as "*.foo"
|
|
|
+ # Avoids needing to quote on command line
|
|
|
+ files="-name *$2"
|
|
|
+ else
|
|
|
+ files="-name ${2}"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ # $3 (if present) is find -mtime arg, default 365
|
|
|
+ if [ ! -z ${3+x} ]; then
|
|
|
+ days="${3}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # set -x
|
|
|
+ find . -type f -mtime -${days} $files -exec egrep --color -H -i "${1}" \{\} \;
|
|
|
+ # set +x
|
|
|
+
|
|
|
+ set +o noglob
|
|
|
+ }
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Bash history functions and settings
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+
|
|
|
+ # Preserve history across sesssions
|
|
|
+ #
|
|
|
+ # http://unix.stackexchange.com/questions/1288/preserve-bash-history-in-multiple-terminal-windows
|
|
|
+ #
|
|
|
+ export HISTCONTROL=ignoredups:erasedups # no duplicate entries
|
|
|
+ export HISTSIZE=100000 # big big history
|
|
|
+ export HISTFILESIZE=100000 # big big history
|
|
|
+ shopt -s histappend # append to history, don't overwrite it
|
|
|
+
|
|
|
+ # Save and reload the history after each command finishes
|
|
|
+ export PROMPT_COMMAND="history -a; history -c; history -r;"
|
|
|
+
|
|
|
+
|
|
|
+ function hgt() {
|
|
|
+ # hgt == "history grep (for arg) tail"
|
|
|
+ #echo "Histroy Grep tail"
|
|
|
+
|
|
|
+ if [ -z ${1+x} ]; then
|
|
|
+ echo 'hgt needs an argument' 1>&2
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ history | grep -i "$1" | tail
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Set the hostnane, timezone and local
|
|
|
+ Set HOSTNAME if ~/etc/hostname exists
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ if [ -e ${HOME}/etc/hostname ]; then
|
|
|
+ export HOSTNAME=`cat ${HOME}/etc/hostname`
|
|
|
+ elif [ -e /etc/hostname ]; then
|
|
|
+ export HOSTNAME=`cat /etc/hostname`
|
|
|
+ else
|
|
|
+ export HOSTNAME="unknown"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Set timezone if ~/bin/tz.sh exists
|
|
|
+
|
|
|
+ # NEW, if neeeed?
|
|
|
+ #
|
|
|
+ # https://linuxize.com/post/how-to-set-or-change-timezone-in-linux/
|
|
|
+ #
|
|
|
+ # OLD:
|
|
|
+ #
|
|
|
+ # if [ -e ~/bin/tz.sh ]; then
|
|
|
+ # echo Setting timezone.
|
|
|
+ # source ~/bin/tz.sh # should be in ~/rc.local
|
|
|
+ # fi
|
|
|
+
|
|
|
+ # STILL NEEDED?
|
|
|
+ #
|
|
|
+ # Set local for numeric output
|
|
|
+ LOCAL=`locale -a | grep -i en_us | head -1`
|
|
|
+ if [[ "$LOCAL" != "" ]]; then export LC_NUMERIC="$LOCAL"; fi
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Set up ssh agent
|
|
|
+ Add keys by hand if needed via
|
|
|
+
|
|
|
+ #+begin_example
|
|
|
+ ssh-add ~/.ssh/id_*
|
|
|
+ #+end_example
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ if [ -e ~/bin/sshagent ]; then
|
|
|
+ source ~/bin/sshagent
|
|
|
+ fi
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Copy stdin to clipboard
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
|
+ alias 2clip='xclip -selection c'
|
|
|
+ alias 3clip='printf %s "$(cat /dev/stdin)" | xclip -selection c' # no final \n
|
|
|
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
|
+ alias 2clip='pbcopy'
|
|
|
+ fi
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Path functions
|
|
|
+ These path* functions add and remove elements to PATH.
|
|
|
+ They insure that entries are unique.
|
|
|
+ They allow you to place a path first or last in the order (e.g.
|
|
|
+ so that ~/bin comes before /usr/local/bin)
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ pathrm() {
|
|
|
+ # remove an item from the path
|
|
|
+ if [ -d "$1" ]; then
|
|
|
+ removeThis="`echo $1 | sed -e 's#/#\\\/#'g`"
|
|
|
+ newPath=`echo $PATH | awk -v RS=: -v ORS=: "/$removeThis/ {next} {print}" | sed 's/[ :]*$//g'`
|
|
|
+ export PATH=$newPath
|
|
|
+ fi
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ pathlast() {
|
|
|
+ # add path to the end if not there
|
|
|
+ if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
|
|
|
+ export PATH="${PATH:+"$PATH:"}$1"
|
|
|
+ fi
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ pathfirst() {
|
|
|
+ # add path to the front if not there
|
|
|
+ if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
|
|
|
+ export PATH="$1:${PATH}"
|
|
|
+ fi
|
|
|
+ }
|
|
|
+
|
|
|
+ path() {
|
|
|
+ # show path
|
|
|
+ echo $PATH
|
|
|
+ }
|
|
|
+
|
|
|
+ # show path, one entry per line
|
|
|
+ alias pathcat="echo $PATH | sed 's/:/\n/g'"
|
|
|
+
|
|
|
+
|
|
|
+ # Be sure we have a few specific paths if they exist
|
|
|
+
|
|
|
+ pathlast $HOME/bin
|
|
|
+ pathlast /usr/local/bin
|
|
|
+ pathlast /opt/bin
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** source ~/rc.local/*.sh to do non-general bash setup
|
|
|
+ Execute any .sh files in ~/rc.local/*.sh
|
|
|
+
|
|
|
+ This allows me to split out setup for aliases and commands that
|
|
|
+ only get used on certian systems or in certian contexts (git, go,
|
|
|
+ mail, blog..)
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+
|
|
|
+ if [ -d ${HOME}/rc.local ]; then
|
|
|
+ for rcfile in $(find ${HOME}/rc.local -name \*.sh); do
|
|
|
+ debug running localrc ${rcfile}
|
|
|
+ source ${rcfile}
|
|
|
+ done
|
|
|
+ fi
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Invoking emacs
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ alias emacs='setsid emacs'
|
|
|
+
|
|
|
+ # from http://stuff-things.net/2014/12/16/working-with-emacsclient/
|
|
|
+
|
|
|
+ if [ -z "$SSH_CONNECTION" ]; then
|
|
|
+ export EMACSCLIENT=emacsclient
|
|
|
+ alias ec="$EMACSCLIENT -c -n"
|
|
|
+ export EDITOR="$EMACSCLIENT -c"
|
|
|
+ export ALTERNATE_EDITOR=""
|
|
|
+ else
|
|
|
+ export EDITOR=$(type -P emacs || type -P ed)
|
|
|
+ fi
|
|
|
+ export VISUAL=$EDITOR
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** ls aliases
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+
|
|
|
+ # coloring for ls functions
|
|
|
+
|
|
|
+ if [[ "$OSTYPE" == "linux-gnu" ]]; then
|
|
|
+ color="--color";
|
|
|
+ else
|
|
|
+ color=""
|
|
|
+ fi
|
|
|
+
|
|
|
+ BIN_LS=/bin/ls
|
|
|
+ alias ls=' ls '$color' -a'
|
|
|
+
|
|
|
+
|
|
|
+ # Long List Reverse Tail
|
|
|
+ function llrt() { ls -lrt $color ${*:-}; }
|
|
|
+
|
|
|
+ # Long List Time
|
|
|
+ function llt() { ls -lt $color ${*:-}; }
|
|
|
+
|
|
|
+ # Long List Time, More
|
|
|
+ function lltm() { ls -lt $color ${*:-} | more; }
|
|
|
+
|
|
|
+ # Long List Time, Less
|
|
|
+ function lltl() { ls -alt $color ${*:-} | more; }
|
|
|
+
|
|
|
+ # Long List Time, Head
|
|
|
+ function llth() { ls -lt $color ${*:-} | head; }
|
|
|
+
|
|
|
+ # Long List Time, Tail
|
|
|
+ function lltt() { ls -alt $color ${*:-} | tail; }
|
|
|
+
|
|
|
+
|
|
|
+ # List Sort Size
|
|
|
+ function lss() { ls -a1s $color ${*:-} | sort -n; }
|
|
|
+
|
|
|
+ # List Sort Size Reverse
|
|
|
+ function lssr() { ls -a1s $color ${*:-} | sort -nr; }
|
|
|
+
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** Aliases for viewing the newest file in a directoy
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+
|
|
|
+ function nf ()
|
|
|
+ {
|
|
|
+ # list the newest file in the current directory
|
|
|
+ NF=`find ${1:-.} -maxdepth 1 -type f -print0 | xargs -0 ls -1t | head -1;`;
|
|
|
+ echo ${NF:-/dev/null} | sed "s/ /\\\ /g"
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ # new file tail file
|
|
|
+ function nftf { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs tail -f ; }
|
|
|
+
|
|
|
+ # new file tail
|
|
|
+ function nft { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs tail ; }
|
|
|
+
|
|
|
+ # new file head
|
|
|
+ function nfh { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs head ; }
|
|
|
+
|
|
|
+ # new file less
|
|
|
+ function nfl { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs less ; }
|
|
|
+
|
|
|
+ # new file cat
|
|
|
+ function nfc { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs cat ; }
|
|
|
+
|
|
|
+ # new file ls
|
|
|
+ function nfls { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs ls -A1t ; }
|
|
|
+
|
|
|
+ # new file ls -l
|
|
|
+ function nflsl { NF=`nf ${1:-.}`; debug NF $NF; echo "$NF" | xargs
|
|
|
+ ls -Atl ; }
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** viewing files
|
|
|
+ Notes on setting up file/mime type assiciatons
|
|
|
+ https://unix.stackexchange.com/questions/77136/xdg-open-default-applications-behavior
|
|
|
+
|
|
|
+ So...
|
|
|
+
|
|
|
+ locate -r 'emacs.*\.desktop'
|
|
|
+ xdg-mime default emacs.desktop text/plain
|
|
|
+
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ if [[ ! -z "`which xdg-open`" ]]; then alias open='xdg-open '; fi
|
|
|
+ #+end_src
|
|
|
+
|
|
|
+** All done
|
|
|
+ #+begin_src shell :tangle .bashrc.sh :noweb no-export
|
|
|
+ touch $HOME/.bashrc-ran
|
|
|
+ debug ".bashrc done"
|
|
|
+ #+end_src
|