Last active
May 8, 2021 00:50
-
-
Save redguardtoo/cd5ea2251e0a12fa31a28567b13f741e to your computer and use it in GitHub Desktop.
My bash configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# Bash 4+ required | |
# FROM, | |
# 1. http://tldp.org/LDP/abs/html/sample-bashrc.html | |
# 2. git://github.com/chenkaie/DotFiles.git | |
## | |
# If not running interactively, don't do anything | |
case $- in | |
*i*) ;; | |
*) return;; | |
esac | |
# Quit if bash version is less than 4 | |
# by default, OSX use Bash 3 | |
# @see https://github.com/mooz/percol/issues/14#issuecomment-150964987 | |
# but you can upgrade bash | |
# @see http://clubmate.fi/upgrade-to-bash-4-in-mac-os-x/ | |
if [ "${BASH_VERSION%%[^0-9]*}" -lt "4" ]; then | |
return; | |
fi | |
# Source global definitions (if any) | |
if [ -f /etc/bashrc ]; then | |
. /etc/bashrc # --> Read /etc/bashrc, if present. | |
fi | |
# Gentoo Linux | |
if [ -f /etc/bash/bashrc ]; then | |
. /etc/bash/bashrc | |
fi | |
# for what distribution? | |
if [ -f /etc/bash.bashrc ]; then | |
. /etc/bash.bashrc | |
fi | |
function xpop() { | |
xprop | grep --color=none "WM_CLASS\|^WM_NAME" | xmessage -file - | |
} | |
function p() { | |
ps axu | grep "$@" | |
} | |
# {{ Shell in Emacs sets $TERM to "dumb" | |
if [ "${TERM}" != "dumb" ]; then | |
# enable bash completion | |
# @see http://www.simplicidade.org/notes/archives/2008/02/bash_completion.html | |
if [ -f /etc/bash_completion ]; then | |
# ArchLinux | |
. /etc/bash_completion | |
elif [ -f /etc/profile.d/bash-completion.sh ]; then | |
# Gentoo Linux | |
. /etc/profile.d/bash-completion.sh | |
elif [ ! -z $BASH_COMPLETION ]; then | |
. $BASH_COMPLETION | |
fi | |
fi | |
# }} | |
if [ -d $HOME/bash_completion.d ]; then | |
. $HOME/bash_completion.d/gibo-completion.bash | |
. $HOME/bash_completion.d/git-completion.bash | |
fi | |
if [ "$OSTYPE" = "cygwin" ]; then | |
OS_NAME='CYGWIN' | |
elif [ "`uname -s`" = "Darwin" ]; then | |
OS_NAME="Darwin" | |
elif grep -q Microsoft /proc/version; then | |
OS_NAME="WSL" | |
else | |
OS_NAME=`uname -r` | |
fi | |
# [ $(uname -s | grep -c CYGWIN) -eq 1 ] && OS_NAME="CYGWIN" || [ $(cat /proc/version | grep -c Microsoft) -eq 1 ] && OS_NAME="WSL" || OS_NAME=`uname -s` | |
#tomcat root dir on archlinux | |
# Please note `$HOME/bin` already defined in ~/.profile | |
export PATH=$HOME/bin:$PATH:/usr/lib/ccache/bin:$HOME/Games | |
export DTK_PROGRAM=espeak | |
export MOZ_DISABLE_PANGO=1 #disable pango of firefox | |
# See what we have to work with ... | |
HAVE_VIM=$(command -v vim) | |
HAVE_GVIM=$(command -v gvim) | |
# EDITOR | |
test -n "$HAVE_VIM" && EDITOR=vim || EDITOR=vi | |
export EDITOR | |
#bug in this .bashrc? | |
HOST=0 | |
# Easy extact | |
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 ;; | |
*.odt) 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 | |
} | |
# easy compress - archive wrapper | |
compress () { | |
if [ -n "$1" ] ; then | |
FILE=$1 | |
case $FILE in | |
*.tar) shift && tar cf $FILE $* ;; | |
*.tar.bz2) shift && tar cjf $FILE $* ;; | |
*.tar.gz) shift && tar czf $FILE $* ;; | |
*.tgz) shift && tar czf $FILE $* ;; | |
*.zip) shift && zip $FILE $* ;; | |
*.rar) shift && rar $FILE $* ;; | |
esac | |
else | |
echo "usage: compress <foo.tar.gz> ./foo ./bar" | |
fi | |
} | |
function relativepath() { | |
# both $1 and $2 are absolute paths beginning with / | |
# returns relative path to $2/$target from $1/$source | |
local source=$1 | |
local target=$2 | |
common_part=$source # for now | |
result="" # for now | |
while [[ "${target#$common_part}" == "${target}" ]]; do | |
# no match, means that candidate common part is not correct | |
# go up one level (reduce common part) | |
common_part="$(dirname $common_part)" | |
# and record that we went back, with correct / handling | |
if [[ -z $result ]]; then | |
result=".." | |
else | |
result="../$result" | |
fi | |
done | |
if [ "$common_part" = "/" ]; then | |
# special case for root (no common path) | |
result="$result/" | |
fi | |
# since we now have identified the common part, | |
# compute the non-common part | |
forward_part="${target#$common_part}" | |
# and now stick all parts together | |
if [[ -n $result ]] && [[ -n $forward_part ]]; then | |
result="$result$forward_part" | |
elif [[ -n $forward_part ]]; then | |
# extra slash removal | |
result="${forward_part:1}" | |
fi | |
echo $result | |
} | |
function relativepwd() { | |
relativepath $PWD $1 | |
} | |
function ssa2srt() { | |
# ssa should be utf-8 format | |
for i in *.ssa ; do ffmpeg -i "$i" "$i.srt" ; done | |
} | |
# xclip has some problem with my emacs, so I use xsel for everything | |
function gclip() { | |
if [ "$OS_NAME" = "CYGWIN" ]; then | |
cat /dev/clipboard | |
elif [ "$OS_NAME" = "Darwin" ]; then | |
pbpaste $@; | |
elif hash powershell.exe 2>/dev/null; then | |
powershell.exe -command Get-Clipboard | |
elif [ -x /usr/bin/xsel ]; then | |
xsel -ob $@; | |
elif [ -x /usr/bin/xclip ]; then | |
xclip -o $@; | |
else | |
echo "Neither xsel or xclip is installed!" | |
fi | |
} | |
function pclip() { | |
if [ "$OS_NAME" = "CYGWIN" ]; then | |
# https://stackoverflow.com/questions/29501860/how-can-bash-read-from-piped-input-or-else-from-the-command-line-argument | |
echo -n $(cat) >> /dev/clipboard | |
elif [ "$OS_NAME" = "Darwin" ]; then | |
pbcopy $@; | |
elif hash clip.exe 2>/dev/null; then | |
# Linux sub-system on Windows 10 | |
clip.exe $@ | |
elif [ -x /usr/bin/xsel ]; then | |
xsel -ib $@; | |
elif [ -x /usr/bin/xclip ]; then | |
xclip -selection c $@; | |
else | |
echo "Neither xsel or xclip is installed!" | |
fi | |
} | |
function fzfnormal { | |
if [ -x $HOME/bin/fzf ]; then | |
# `-e` to turn off fuzzy match | |
$HOME/bin/fzf -e --reverse --cycle -1 -0 -m "$@" | |
else | |
python $HOME/bin/percol.py "$@" | |
fi | |
} | |
function h () { | |
# reverse history, pick up one line, remove new line characters and put it into clipboard | |
if [ -z "$1" ]; then | |
echo "Usage: h keyword [-v]" | |
echo " '-v' will filter OUT matched you typing interactively" | |
else | |
history | grep "$1" | sed '1!G;h;$!d' | fzfnormal $2 | sed -n 's/^ *[0-9][0-9]* *\(.*\)$/\1/p'| tr -d '\n' | pclip | |
fi | |
} | |
# @see https://www.techrepublic.com/article/find-and-bind-key-sequences-in-bash/ | |
# run `read' in shell and press "M-n", got "^[n", "^]" is equivalent to [ESC] key | |
bind -x '"\en": READLINE_LINE=$(history | grep "${READLINE_LINE}" | sed "1!G;h;\$!d" | fzfnormal | sed "s/^ *[0-9]* *//g") READLINE_POINT=' | |
## | |
# Automatic setting of $DISPLAY (if not set already) | |
# This works for linux - your mileage may vary.... | |
# The problem is that different types of terminals give | |
# different answers to 'who am i'...... | |
# I have not found a 'universal' method yet | |
## | |
function get_xserver () | |
{ | |
case $TERM in | |
xterm ) | |
XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' ) | |
# Ane-Pieter Wieringa suggests the following alternative: | |
# I_AM=$(who am i) | |
# SERVER=${I_AM#*(} | |
# SERVER=${SERVER%*)} | |
XSERVER=${XSERVER%%:*} | |
;; | |
aterm | rxvt) | |
# find some code that works here..... | |
;; | |
esac | |
} | |
if [ -z ${DISPLAY:=""} ]; then | |
get_xserver | |
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || | |
${XSERVER} == "unix" ]]; then | |
DISPLAY=":0.0" # Display on local host | |
else | |
DISPLAY=${XSERVER}:0.0 # Display on remote host | |
fi | |
fi | |
export DISPLAY | |
## | |
# Some settings | |
## | |
set -o notify | |
#set -o noclobber | |
set -o ignoreeof | |
set -o nounset | |
#set -o xtrace # Useful for debuging | |
if [ "`echo $BASH_VERSION | cut -b 1`" -eq "4" ]; then | |
# BASH version 4 | |
shopt -s dirspell | |
# * `autocd`, e.g. `**/qux` will enter `./foo/bar/baz/qux` | |
shopt -s autocd | |
# * Recursive globbing, e.g. `echo **/*.txt` | |
shopt -s globstar | |
# Autocorrect typos in path names when using `cd` | |
shopt -s cdspell | |
export PROMPT_DIRTRIM=3 | |
fi | |
export PROMPT_COMMAND="history -a" | |
# Case-insensitive globbing (used in pathname expansion) | |
shopt -s nocaseglob | |
# Treat every non-directory argument to the `cd` as variable containing a directory to cd into. `cd WXWIN` for example | |
shopt -s cdable_vars | |
# Checks a command found in the hash table exists before trying to execute it. If a hashed command no longer exists, a normal path search is performed | |
shopt -s checkhash | |
# check window size after each command and, if necessary, updates variables LINES and COLUMNS | |
shopt -s checkwinsize | |
# the source builtin command uses $PATH to find directory containing the file supplied as an argument. This option is enabled by default. | |
shopt -s sourcepath | |
# not attempt to search the PATH for possible completions when completion is attempted on an empty line | |
shopt -s no_empty_cmd_completion # bash>=2.04 only | |
#save all lines of a multiple-line command in the same history entry. This allows easy re-editing of multi-line commands. | |
shopt -s cmdhist | |
# Append to the Bash history file, rather than overwriting it | |
shopt -s histappend histreedit histverify | |
shopt -s extglob # Necessary for programmable completion | |
# Disable options: | |
shopt -u mailwarn | |
unset MAILCHECK # I don not want my shell to warn me of incoming mail | |
export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n' | |
# @see http://www.talug.org/events/20030709/cmdline_history.html | |
# If you include the expression "[ \t]*" in the HISTIGNORE string, | |
# you cansuppress history recording at will for any given command | |
# just by starting with a space! | |
export HISTCONTROL=ignoreboth:erasedups | |
# Larger bash history (allow 32³ entries; default is 500) | |
export HISTSIZE=32768 | |
export HISTFILESIZE=$HISTSIZE | |
# @see http:/linux.about.com/od/lts_guide/a/gdelts66t00.htm about wildcards | |
export HISTIGNORE="*.aspell.en.pws:*.custom.el:*.gnus.el:*~/.gitconfig:* --version:fg *:which *:h *:?:??:???:????:?????:fcitx*:* --help:* -h:whoami: *:ll *:mkcd *:j:kill *:pkill *:du *:glp *:gnb *:git rc *:git co *:gmt:gr?:g:p4?:p4?? *:z *:man *:extract *:ffcd *" | |
# The FIGNORE environment variable is nice when you want TAB completion to ignore files or folders with certain suffixes, e.g.: | |
export FIGNORE=~:.o:.svn:.git:.swp:.elc:.swa:.pyc:.a:.class:.la:.mo:.obj:.pyo | |
export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts | |
# {{ Define some colors first: | |
# infocmp xterm-256color >/dev/null 2>&1 && export TERM=xterm-256color | |
export MAGENTA="\033[1;31m" | |
export ORANGE="\033[1;33m" | |
export GREEN="\033[1;32m" | |
export PURPLE="\033[1;35m" | |
export WHITE="\033[1;37m" | |
export BOLD="" | |
export RESET="\033[m" | |
# }} | |
# Colored manual pages | |
# Gentoo has some issue, @see http://unix.stackexchangm.com/questions/6010/colored-man-pages-not-working-on-gentoo | |
export LESS_TERMCAP_mb=$'\E[01;31m' # begin blinking | |
export LESS_TERMCAP_md=$'\E[01;38;5;74m' # begin bold | |
export LESS_TERMCAP_me=$'\E[0m' # end mode | |
export LESS_TERMCAP_se=$'\E[0m' # end standout-mode | |
export LESS_TERMCAP_so=$'\E[01;44;33m' # begin standout-mode - info box (search result highlight) | |
export LESS_TERMCAP_ue=$'\E[0m' # end underline | |
export LESS_TERMCAP_us=$'\E[04;38;5;146m' # begin underline | |
export GROFF_NO_SGR=1 | |
# Don’t clear the screen after quitting a manual page | |
export MANPAGER="less -X" | |
# see http://tf.nist.gov/tf-cgi/servers.cgi | |
function adjustclock() | |
{ | |
sudo rdate -s time-c.nist.gov | |
} | |
# Speed up SSH X11 Forwarding | |
function sshx() | |
{ | |
# -X enables X11 forwarding, -C enables compression of all data | |
ssh -X -C $@ | |
} | |
# build ssh tunnel | |
function ssht() | |
{ | |
ssh -qTnNfD 7070 $@ | |
} | |
encrypt () { gpg -ac --no-options "$1"; } | |
decrypt () { gpg --no-options "$1"; } | |
## | |
# Shell Prompt | |
## | |
if [[ "${DISPLAY#$HOST}" != ":0.0" && "${DISPLAY}" != ":0" ]]; then | |
HILIT=${MAGENTA} # remote machine: prompt will be partly red | |
else | |
HILIT=${GREEN} # local machine: prompt will be partly green | |
fi | |
## | |
# Personnal Aliases | |
## | |
function weather { | |
curl wttr.in/$@ | |
} | |
alias starwar="telnet towel.blinkenlights.nl" | |
alias killemacs="pkill -SIGUSR2 emacs" | |
alias cal="LC_ALL=C cal" | |
alias cc="cd -" | |
alias dir="ls" | |
# {{ git | |
# Git alias | |
function gitshortlogcmd () { | |
git log --date=short --decorate --graph "$@" | |
} | |
function gitlogcmd () { | |
git log --date=short --decorate --graph --pretty=format:'%C(yellow)%h%Creset%C(green)%d%Creset %ad %s %Cred(%an)%Creset' "$@" | |
} | |
alias gg="git status --short -b" | |
alias gb="git branch" | |
alias gn="git status --untracked-files=no --short -b" | |
alias gfl="git diff-tree --no-commit-id --name-only -r" | |
alias ga="git add" | |
alias gr="git rebase -i `git remote`/`git symbolic-ref --short HEAD`" | |
alias gap='git add --patch' | |
alias gai='git add -i' | |
alias gau="git add -u" | |
alias gc="git commit -m" | |
alias gca="git commit --amend" | |
alias gja="git --no-pager commit --amend --reuse-message=HEAD" # git just amend | |
alias gtt="git stash" | |
alias gta="git stash apply" | |
alias gmt="git mergetool" | |
alias gme="git mergetool -t ediff" # use emacs to merge conflicts | |
alias gl="gitlogcmd" | |
alias glp="git log -p" # I want to see all details | |
alias gls="gitlogcmd --stat" | |
alias gnb="git checkout -b" | |
alias gss="git show --stat" | |
alias gsl="git log --pretty=format:'%h %s (%an)' --date=short -n1 | pclip" | |
alias gd="git diff" | |
alias gds="git diff --stat" | |
alias gdc="git diff --cached" | |
alias gdcs="git diff --cached --stat" | |
alias gps="git push" | |
alias gpf="git push --force" | |
alias gpl="git pull" | |
alias gpr="git pull -r" | |
alias cg='cd $(git rev-parse --show-toplevel)' #goto root dir | |
# find unmerged "*.html" and "*.min.js", checkout theirs version, and add them | |
alias ghe='git diff --name-only --diff-filter=U|grep "\.html\|\.min\.js"|xargs -I{} sh -c "git checkout --theirs {} && git add {}"' | |
# show diff from the branch to current HEAD | |
alias gdp='git diff $(git branch | sed "s/[\* ]\+//g" | fzfnormal)..HEAD' | |
alias grh='git reset --hard HEAD' | |
alias gr1='git reset --hard HEAD^' | |
alias gr2='git reset --hard HEAD^^' | |
alias gs="git show" | |
# @see https://stackoverflow.com/questions/15292391/is-it-possible-to-perform-a-grep-search-in-all-the-branches-of-a-git-project | |
alias grpa="git branch -a | tr -d \* | sed '/->/d' | xargs git grep" # grep all branches | |
function gsh { | |
git log --date=short --pretty=format:'%h%d %ad %s (%an)' | fzfnormal | awk '{print $1}' | xargs -I{} git show {} | |
} | |
function grpwd { | |
# reset current directory to certain version | |
if [ -z $1 ]; then | |
local ver=`gcid` | |
else | |
local ver=$1 | |
fi | |
if [ -z $ver ]; then | |
echo "Don't know which version to reset" | |
else | |
git checkout $ver . | |
echo "Files are restored to $ver. Run 'git diff --cached' to see them." | |
fi | |
} | |
function gcn() | |
{ | |
# commit with timestamp | |
local d=`date +%m%d-%H%M%S` | |
git commit -m ${d} | |
} | |
# find full path of file who under git controll | |
# the optional parameter is the keyword | |
function gf() | |
{ | |
if [ -z "$1" ]; then | |
local cli=`git ls-tree -r HEAD --name-status | fzfnormal` | |
else | |
local cli=`git ls-tree -r HEAD --name-status | grep "$1" | fzfnormal` | |
fi | |
local rlt=$(cd $(dirname $cli); pwd)/$(basename $cli) | |
echo ${rlt} | |
echo -n ${rlt} | pclip | |
} | |
function glwho () { | |
local guy=`git shortlog -sn | fzfnormal | sed 's/^\s*[0-9]\+\s*//g'` | |
# space is a problem, so we can't use gitshortlogcmd here | |
gitshortlogcmd --pretty=format:'%C(yellow)%h%Creset%C(green)%d%Creset %ad %s %Cred(%an)%Creset' --author="$guy" "$@" | |
} | |
function gfp () { | |
if [ -z "$1" ]; then | |
echo "Usage: gfp since [file]" | |
echo " Just alias of 'git format-patch -n --stdout since -- [file]'" | |
echo " 'gfp since | git am' to apply the patch" | |
fi | |
git format-patch -n --stdout $1 -- $2 | |
} | |
function gcnb () { | |
local remoteb=$(git branch --all | sed '/no branch/d' | fzfnormal) | |
local localb=$(echo $remoteb | sed 's/^ *remotes\/[a-z]*\///g') | |
git checkout -b $localb $remoteb | |
} | |
function grb () { | |
# switch to recent git branch or just another branch | |
local crtb=`git branch | grep \*` | |
local ptn="no branch" | |
# compatible way to detect sub-strin in bash | |
# @see http://stackoverflow.com/questions/229551/string-contains-in-bash | |
if [ -z "${crtb##*$ptn*}" ]; then | |
# detached HEAD | |
git checkout $(git branch | sed '/no branch/d' | fzfnormal) | |
else | |
local myrbs=`git for-each-ref --sort=-committerdate refs/heads/ | sed -e s%.*refs\/heads\/%%g` | |
local crb=`git symbolic-ref --short HEAD` | |
git checkout `echo "$myrbs" | sed '/$crb/d' | fzfnormal` | |
fi | |
} | |
# rebase on LOCAL branches | |
function gri () { | |
local b=`git branch | sed 's/[\* ]\+//g' | fzfnormal` | |
git rebase -i ${b} | |
} | |
# rebase on ALL braches | |
function gra () { | |
local b=`git branch --all | sed 's/[\* ]\+//g' | sed 's/remotes\///g' | fzfnormal` | |
git rebase -i ${b} | |
} | |
# select a local git branch | |
function gsb () { | |
local b=`git branch | sed "s/[\* ]\+//g" | fzfnormal` | |
echo -n ${b} | pclip; | |
echo ${b} | |
} | |
# print current branch name | |
function gcb () { | |
local crb=`git symbolic-ref --short HEAD` | |
echo -n ${crb} | pclip; | |
echo ${crb} | |
} | |
# new local branch based on remote branch | |
function gnr () { | |
local myrb=`git for-each-ref --sort=-committerdate refs/remotes/ | sed -e s%.*refs\/remotes\/%%g | fzfnormal` | |
local mylb=`echo -n $myrb | sed 's/.*\/\([^\/]\+\)$/\1/'` | |
git checkout -b $mylb $myrb | |
} | |
function gchk () { | |
if [ -z "$1" ]; then | |
echo "Usage: gchk commit_id" | |
echo "reset hard certain version of current working directory" | |
else | |
rm -rf $PWD/* | |
git checkout $1 -- $PWD | |
fi | |
} | |
function git2fullpath { | |
local fullpath=$(git rev-parse --show-toplevel)/$1 | |
echo -n $fullpath | pclip | |
echo $fullpath | |
} | |
function glf () { | |
local str=`git --no-pager log --oneline --name-only $* | fzfnormal` | |
git2fullpath $str | |
} | |
function gsf () { | |
local str=`git --no-pager show --pretty=format:'%h %s (%an)' --name-only $* | fzfnormal` | |
git2fullpath $str | |
} | |
function gdf () { | |
local str=`git --no-pager diff --oneline --name-only $*| fzfnormal` | |
git2fullpath $str | |
} | |
function gdcf () { | |
local str=`git --no-pager diff --oneline --cached --name-only $* | fzfnormal` | |
git2fullpath $str | |
} | |
function ggr () { | |
if [ -z "$1" ]; then | |
echo "Grep files under git controll" | |
echo "Usage: ggr [filename-pattern] text-pattern" | |
elif [ $# -eq "1" ]; then | |
git ls-tree -r HEAD --name-only | xargs grep -sn "$1" | |
elif [ $# -eq "2" ]; then | |
git ls-tree -r HEAD --name-only | grep "$1" | xargs grep -sn --color -E "$2" | |
fi | |
} | |
function grpc() { | |
if [ -z "$1" ]; then | |
echo "Replace the content of file in latest git commit" | |
echo "Usage: grpc [commit-hash] old_string new_string (string could be perl regex)" | |
elif [ $# -eq "2" ]; then | |
git diff-tree --no-commit-id --name-only -r HEAD | xargs perl -pi -e "s/$1/$2/g" | |
elif [ $# -eq "3" ]; then | |
git diff-tree --no-commit-id --name-only -r $1 | xargs perl -pi -e "s/$2/$3/g" | |
fi | |
} | |
function grpf() { | |
if [ -z "$1" ]; then | |
echo "Replace the content of file under git" | |
echo "Usage: grpf old_string new_string (string could be perl regex)" | |
elif [ $# -eq "2" ]; then | |
git grep -l "$1" | xargs perl -pi -e "s/$1/$2/g" | |
fi | |
} | |
function gp() { | |
if [ $# = 0 ]; then | |
local from=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^[ *|]*\([a-z0-9]*\) .*$/\1/"`; | |
local fn=from-$from-`date +%Y%m%d-%H%M`.patch | |
git format-patch -n --stdout $from > $fn && ls $fn | |
else | |
local fn=from-$1-`date +%Y%m%d-%H%M`.patch | |
git format-patch -n --stdout $1 > $fn && ls $fn | |
fi; | |
} | |
# }} | |
# {{ subversion | |
# svn v1.7+ | |
alias svr="svn revert" | |
alias svrh="svn revert -R ." # git reset hard | |
alias sv="svn status" | |
alias svu="svn update" | |
alias svc="svn commit -m" | |
alias svds="svn diff --diff-cmd=diff | lsdiff" | |
function cs () | |
{ | |
# @see http://stackoverflow.com/questions/1242364/how-can-i-find-the-root-folder-of-a-given-subversion-working-copy | |
# go to subversion root, subversion 1.7+ | |
# could be easily extended to other vcs. | |
# but for now let's focus on svn only | |
local parent="" | |
local grandparent="." | |
while [ ! -d "$grandparent/.svn" ]; do | |
parent=$grandparent | |
grandparent="$parent/.." | |
done | |
if [ ! -z "$grandparent" ]; then | |
cd $grandparent | |
fi | |
} | |
function svds() | |
{ | |
# patchutils required | |
svn diff "$*" | lsdiff | |
} | |
function svd() | |
{ | |
svn diff "$*" | less -r | |
} | |
function svl(){ | |
if [ -f $HOME/bin/svn_short_log ]; then | |
svn log "$*" | $HOME/bin/svn_short_log | less -r | |
else | |
svn log "$*" | less -r | |
fi | |
} | |
function svlp(){ | |
svn log "$*" --diff | less -r | |
} | |
function svc(){ | |
svn commit -m "$*" | |
} | |
function svs(){ | |
svn diff -c $* | less -r | |
} | |
function svss(){ | |
svn diff --summarize -c $* | |
} | |
function svdf () { | |
# svn diff and select a file | |
local str=`svn diff --diff-cmd=diff $* | lsdiff | fzfnormal` | |
if [[ $str =~ ^[[:space:]]*([a-z0-9A-Z_.\/-]*).*$ ]]; then | |
echo -n ${BASH_REMATCH[1]} |pclip; | |
echo ${BASH_REMATCH[1]} | |
fi | |
} | |
# }} | |
function frp(){ | |
if [ -z "$1" ]; then | |
echo "Usage: frp old_string new_string (string could be perl regex)" | |
echo "replace the content of regular file in $PWD" | |
else | |
find . -type f -print0 | xargs -0 perl -i -pe's/$1/$2/g' | |
fi | |
} | |
function grepcmd () { | |
if hash rg 2>/dev/null; then | |
# @see http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script | |
rg -s -n -g="!archive-contents" -g='!.git/*' -g='!.bzr/*' -g='!.svn/*' -g='!bower_components/*' -g='!node_modules/*' -g='!.sass-cache/*' -g='!.cache/*' -g='!test/*' -g='!tests/*' -g='!.metadata/*' -g='!logs/*' -g='!*.log' -g='!*.properties' -g='!*.session' -g='!*.swp' -g='!TAGS' -g='!tags' -g='!GTAGS' -g='!GPATH' -g='!.bookmarks.el' -g='!*.svg' -g='!history' -g='!#*#' -g='!*.min.js' -g='!*bundle*.js' -g='!*vendor*.js' -g='!*.min.css' -g='!*~' "$@" | |
else | |
grep -rsnI --exclude='archive-contents' --exclude='*.log' --exclude='*.properties' --exclude='TAGS' --exclude=tags --exclude=GTAGS --exclude-dir=.svn --exclude-dir=bower_components --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.sass-cache --exclude-dir=.cache --exclude-dir=.cvs --exclude-dir=.git --exclude-dir=test --exclude-dir=tests --exclude-dir=.hg --exclude-dir=.metadata --exclude-dir=logs --exclude='#*#' --exclude='*.swp' --exclude='*.min.js' --exclude='*.min.css' --exclude='*~' --color=auto "$@" | |
fi | |
} | |
# remove beginning ??, UU, space, CC, +, - and trailing + = | |
function pl () { | |
fzfnormal | sed -e "s/^[\?\|MUA ]\{1,2\}[ \t][ \t ]*//g" | sed -e "s/[ \t][0-9\+\| \t-]*$//g" | tr -d "\n" | pclip | |
} | |
function fef () { | |
if [ -z "$1" ]; then | |
echo "Usage: fef file-extension PATTERN" | |
echo "Find file containing PATTERN wiht file-extension" | |
echo "Example: fef scss sup" | |
else | |
find . -type f \( -path .fseventsd -path .svn -o -path .git -o -path .hg -o -path .sass-cache -o -path node_modules -o -path .cache \) -prune -o -name "$1" -exec grep -l "$2" {} \; | fzfnormal | sed -e "s%^ *\([a-z0-9A-Z_.\/-]*\).*%\1%"|tr -d "\n" | pclip | |
fi | |
} | |
function fge () { | |
if [ -z "$1" ]; then | |
echo "Usage: fge file-extension PATTERN" | |
echo "Find file containing PATTERN wiht file-extension" | |
echo "Example: fge scss sup" | |
else | |
find . -type f \( -path .svn -o -path .git -o -path .hg -o -path .sass-cache -o -path node_modules -o -path .cache \) -prune -o -name "$1" -exec grep -sn "$2" {} \; | |
fi | |
} | |
function a () { | |
grepcmd "$@" | |
} | |
function af () { | |
local filename=`grepcmd "$@" | fzfnormal | sed -e "s%^ *\([a-z0-9A-Z_.\/+-]*\).*%\1%"|tr -d "\n"` | |
if [ ! -z "$filename" ];then | |
echo -n "$PWD/$filename" | pclip | |
echo `gclip` | |
fi | |
} | |
# change relative path to full path | |
function fp () { | |
local str=$PWD/$* | |
echo -n ${str} |pclip; | |
echo ${str} | |
} | |
# {{ git tools to handle commit id | |
function gurl () { | |
if [ -z "$1" ]; then | |
echo "Usage: gurl commit-id" | |
echo "get the full http url of commit" | |
else | |
local msg=`git remote -v|grep "origin *.* *(fetch)"|sed -e "s/origin *\(.*\) *(fetch)/\1/"` | |
local url="" | |
# github | |
if [ "${msg:0:14}" = "[email protected]" ]; then | |
echo https://github.com/`echo ${msg}|sed -e "s/^git\@github\.com\:\(.*\)\.git$/\1/"`/commit/$1 | |
fi | |
fi | |
} | |
# pick commit id from `git log` | |
function gcid () { | |
local commit_id=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^[ *|]*\([a-z0-9]*\) .*$/\1/"` | |
echo ${commit_id} | |
} | |
function ggp () { | |
git format-patch -n --stdout `gcid` | |
} | |
#pick commit from `git log` and output its url | |
function gqurl () { | |
local commit_id=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^\([a-z0-9]*\) .*$/\1/"` | |
gurl ${commit_id} | |
} | |
# find files between commit and HEAD and grep | |
alias glfge='git diff-tree --no-commit-id --name-only -r `gcid` -r HEAD|xargs grepcmd' | |
# git push origin to selected commit | |
function gpss () { | |
local pushopt="`gcid`:`gcb`" | |
if [ ${#pushopt} -ge 8 ]; then | |
git push origin $pushopt | |
else | |
echo "Nothing pushed" | |
fi | |
} | |
# rebase on origin | |
function grm () { | |
git rebase -i origin `gcb` | |
} | |
# analyze text from stdin and open file and line number with vi | |
function grepo () { | |
if [ -z "$1" ]; then | |
echo "Usage: grepo regex file(s)" | |
echo "grep the file(s) and open the user choosen file with specific line number" | |
echo "the full path of the file will be put into clipboard" | |
else | |
local rlt=`grepcmd "$1" ${PWD}/*| fzfnormal` | |
local vim_options=`echo $rlt|sed -e"s/^\([^:]*\):\([0-9]*\):.*/+\2 \1/g"` | |
# also put the full file path into clipboard | |
echo $rlt|sed -e"s/^\([^:]*\):\([0-9]*\):.*/\1/g"|pclip | |
#echo "vim_options=$vim_options" | |
vim ${vim_options} | |
fi | |
} | |
function prepend(){ | |
if [ -z "$1" ]; then | |
echo "Usage: prepend line file" | |
echo "prepend a line into the file. The line could contain CR" | |
else | |
sed -i -e "1i $1" $2 | |
fi | |
} | |
function bye () { | |
if [ "$OS_NAME" = "CYGWIN" ]; then | |
shutdown -t 3 -f -s | |
else | |
sudo shutdown -h now | |
fi | |
} | |
function slp () { | |
if [ "$OS_NAME" = "CYGWIN" ]; then | |
# hibernate | |
rundll32.exe PowrProf.dll,SetSuspendState | |
elif [ "$OS_NAME" = "Darwin" ]; then | |
pmset sleepnow | |
else | |
# sleep | |
sudo pm-suspend | |
fi | |
} | |
function rbt() { | |
if [ "$OS_NAME" = "CYGWIN" ]; then | |
shutdown -t 3 -f -r | |
elif [ "$OS_NAME" = "Darwin" ]; then | |
sudo reboot | |
else | |
sudo reboot | |
fi | |
} | |
function memfs() { | |
mkdir -p ~/tmp;sudo mount -t tmpfs tmpfs ~/tmp -o size=$@ | |
} | |
# turn on/off the screen | |
alias von='sudo vbetool dpms on' | |
alias voff='sudo vbetool dpms off' | |
# sort and count lines, | |
#@see http://felipec.wordpress.com/2011/06/02/command-history-meme/ | |
#alias cntl=awk '{a[$1]++} END{for(i in a){printf "%5d\t%s\n",a[i],i}}'|sort -rn | |
alias my='mystartx' #start my favourit WM | |
# example, convertdoc pdf *.odt | |
alias convertdoc="soffice --headless --invisible --convert-to" | |
#Example: rsync -avz --delete /home/username/ /media/disk/backup | |
alias bkrsync="rsync -avz --delete" | |
#grep and its alternatives | |
#@see http://stackoverflow.com/questions/221921/grep-exclude-include- \ | |
#syntax-do-not-grep-through-certain-files | |
alias vncsvr1440='vncserver -geometry 1440x900 -depth 16 :1' | |
alias gfw='python ~/bin/goagent/proxy.py >/dev/null 2>&1' | |
alias rd='rdesktop -fP' | |
alias cp='cp ' | |
alias mv='mv ' | |
# -> Prevents accidentally clobbering files. | |
#I need clip between firefox | |
alias j='jobs -l' | |
alias which='type -all' | |
alias path='echo -e ${PATH//:/\\n}' | |
alias print='/usr/bin/lp -o nobanner -d $LPDEST' | |
# Assumes LPDEST is defined | |
alias pjet='enscript -h -G -fCourier9 -d $LPDEST' | |
# Pretty-print using enscript | |
alias background='xv -root -quit -max -rmode 5' | |
# Put a picture in the background | |
alias du='du -kh' | |
alias dush='du -sh' | |
alias wget='wget -c' | |
# {{ emacs stuff | |
# install source code | |
if [ "$OS_NAME" = "Darwin" ] ; then | |
# set up PATH so .gitconfig can pick up right version of Emacs | |
if [ -x /Applications/Emacs.app/Contents/MacOS/Emacs ]; then | |
# `brew install --with-cocoa --srgb emacs` on OS X | |
ln -sf /Applications/Emacs.app/Contents/MacOS/Emacs $HOME/bin/emacs | |
elif [ -x $HOME/Applications/Emacs.app/Contents/MacOS/Emacs ]; then | |
ln -sf $HOME/Applications/Emacs.app/Contents/MacOS/Emacs $HOME/bin/emacs | |
fi | |
fi | |
function e() | |
{ | |
if [ "$TERM" = "linux" ]; then | |
# minimum linux console | |
emacs -nw "$@" | |
elif [ -x $HOME/myemacs/26.1/bin/emacs ]; then | |
if [ "$TERM" = "rxvt" ]; then | |
# rxvt support 256 colors | |
TERM=xterm-256color $HOME/myemacs/26.1/bin/emacs -nw "$@" | |
else | |
TERM=xterm-24bits $HOME/myemacs/26.1/bin/emacs -nw "$@" | |
fi | |
elif [ "$OS_NAME" = "Darwin" ]; then | |
if [ -x $HOME/Applications/Emacs.app/Contents/MacOS/Emacs ]; then | |
TERM=xterm-24bits $HOME/Applications/Emacs.app/Contents/MacOS/Emacs -nw "$@" | |
else | |
TERM=xterm-24bits emacs -nw "$@" | |
fi | |
else | |
TERM=xterm-256color emacs -nw "$@" | |
fi | |
} | |
function ee() | |
{ | |
if [ "$TERM" = "linux" ]; then | |
# minimum linux console | |
emacs -nw "$@" | |
else | |
TERM=xterm-256color emacs -nw "$@" | |
fi | |
} | |
function te() | |
{ | |
if [ "$TERM" = "linux" ]; then | |
tsocks emacs -nw "$@" | |
else | |
TERM=xterm-256color tsocks emacs "$@" | |
fi | |
} | |
# }} | |
function odt2doc() { | |
if [ "$OS_NAME" = "Darwin" ]; then | |
/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to doc "$@" | |
else | |
soffice --headless --convert-to doc "$@" | |
fi | |
} | |
function odt2pdf() { | |
if [ "$OS_NAME" = "Darwin" ]; then | |
/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to doc "$@" | |
else | |
soffice --headless --convert-to pdf "$@" | |
fi | |
} | |
if [ "$OS_NAME" = "Darwin" ]; then | |
alias df='df -kh' | |
alias ll='ls -l' | |
else | |
alias df='df -kTh' | |
# The 'ls' family (this assumes you use the GNU ls) | |
alias ls='ls --show-control-chars --color=auto -hF' | |
alias lx='ls -lXB' # sort by extension | |
function ll() | |
{ ls -l "$@"| egrep "^d" ; ls -lXB "$@" 2>&-| egrep -v "^d|total "; } | |
fi | |
alias l1='ls -1' | |
alias lr='ls -lR' # recursive ls | |
alias tree='tree -Csu' # nice alternative to 'ls' | |
alias update-mpd-list="cd ~/Music;find . -name '*.mp3' -o -name '*.flac'|sed -e 's%^./%%g' > all.m3u;mpd ~/.mpd/config;mpc clear;mpc load all.m3u;mpc update" | |
#@see http://stackoverflow.com/questions/3746/whats-in-your-bashrc | |
alias cd..="cd .." | |
alias ..="cd .." | |
alias ...="cd ../.." | |
alias ....="cd ../../.." | |
function m () { | |
$* --help | less | |
} | |
# smarter locate | |
function baseoo() { | |
local s=$@ | |
local keyword=${s// /.*} | |
if [ "$OS_NAME" = "Darwin" ]; then | |
local file=`locate -i "${keyword}" | fzfnormal` | |
else | |
local file=`locate -i --regex "${keyword}" | fzfnormal` | |
fi | |
echo -n $file | |
} | |
function of() { | |
local f=`baseoo $*` | |
echo ${f} | |
echo -n ${f} | pclip | |
} | |
function oo() { | |
local f=`baseoo $*` | |
if [ "$OS_NAME" = "Darwin" ]; then | |
echo $f | xargs open & | |
else | |
echo $f | xargs xdg-open & | |
fi | |
} | |
#gcc | |
alias objdump='objdump -d -S -hrt' | |
# spelling typos - highly personnal :-) | |
alias nospan="sed 's%</*span[^>]*>%%g'" | |
function mk() { | |
if [ "$OS_NAME" = "Darwin" ]; then | |
make -j`sysctl -n hw.ncpu` | |
else | |
make -j`nproc` | |
fi | |
} | |
function nj() { | |
if [ "$OS_NAME" = "Darwin" ]; then | |
ninja -j`sysctl -n hw.ncpu` | |
else | |
ninja -j`nproc` | |
fi | |
} | |
## File & strings related functions: | |
# search the file and pop up dialog, then put the full path in clipboard | |
# usage: baseff (file|dir) keyword | |
# is used as API instead of user command | |
function baseff() | |
{ | |
local fullpath=$2 | |
local filename=${fullpath##*./} # remove ".../" from the beginning | |
# - only the filename without path is needed | |
# - filename should be reasonable | |
if [ "$1" = "file" ] || [ "$1" = "relfile" ];then | |
if hash fd 2>/dev/null;then | |
local rlt=`fd --full-path -H --type f -E'.git/*' -E'vendor/*' -E'.svn/*' -E'.npm/*' -E'.backups/*' -E'.hg/*' -E'node_modules/*' -I ".*${filename}.*" | fzfnormal` | |
else | |
local rlt=`find . \( -iwholename '*#' -o -iwholename '*/.backups/*' -o -iwholename '*/deployment/*' -o -iwholename '*/_doc/*' -o -iwholename '*/test/*' -o -iwholename '*/coverage/*' -o -iwholename '*/.gradle/*' -o -iwholename '*~' -o -iwholename '*.swp' -o -iwholename '*/dist/*' -o -iwholename '*.class' -o -iwholename '*.js.html' -o -iwholename '*.elc' -o -iwholename '*.pyc' -o -iwholename '*/bin/*' -o -iwholename '*/.config/*' -o -iwholename '*/vendor/*' -o -iwholename '*/bower_components/*' -o -iwholename '*/node_modules/*' -o -iwholename '*/.svn/*' -o -iwholename '*/.git/*' -o -iwholename '*/.gitback/*' -o -iwholename '*/.npm/*' -o -iwholename '*.sass-cache*' -o -iwholename '*/.hg/*' \) -prune -o -type f -iwholename '*'${filename}'*' -print | fzfnormal` | |
fi | |
else | |
if hash fd 2>/dev/null;then | |
local rlt=`fd --full-path -H --type d -E'.git/*' -E'vendor/*' -E'.svn/*' -E'.npm/*' -E'.backups/*' -E'.hg/*' -E'node_modules/*' -I ".*${filename}.*" | fzfnormal` | |
else | |
local rlt=`find . \( -iwholename '*#' -o -iwholename '*/.backups/*' -o -iwholename '*/deployment/*' -o -iwholename '*/_doc/*' -o -iwholename '*/test/*' -o -iwholename '*/coverage/*' -o -iwholename '*/.gradle/*' -o -iwholename '*~' -o -iwholename '*.swp' -o -iwholename '*/dist/*' -o -iwholename '*.class' -o -iwholename '*.js.html' -o -iwholename '*.elc' -o -iwholename '*.pyc' -o -iwholename '*/bin/*' -o -iwholename '*/.config/*' -o -iwholename '*/vendor/*' -o -iwholename '*/bower_components/*' -o -iwholename '*/node_modules/*' -o -iwholename '*/.svn/*' -o -iwholename '*/.git/*' -o -iwholename '*/.gitback/*' -o -iwholename '*/.npm/*' -o -iwholename '*.sass-cache*' -o -iwholename '*/.hg/*' \) -prune -o -type d -iwholename '*'${filename}'*' -print | fzfnormal` | |
fi | |
fi | |
if [ -z "${rlt}" ];then | |
echo "" | |
else | |
if [ "$1" = "relfile" ]; then | |
# use relative path | |
echo $rlt | |
else | |
# convert relative path to full path | |
echo $(cd $(dirname $rlt); pwd)/$(basename $rlt) | |
fi | |
fi | |
} | |
# find a file and copy its *nix full path into clipboard | |
function ff { | |
local cli=`baseff file $*` | |
echo ${cli} | |
echo -n ${cli} | pclip | |
} | |
function ii { | |
local cli=`baseff file $* | xargs echo -n` | |
if [[ "${cli}" =~ ".png" ]]; then | |
echo -n ${cli} | xargs -I{} xclip -selection clipboard -t image/png -i {} | |
echo "${cli} => clipboard" | |
fi | |
} | |
# any file on this computer | |
function aa { | |
if [ -z "$1" ]; then | |
local cli=`locate / | fzfnormal` | |
else | |
local cli=`locate "$1" | fzfnormal` | |
fi | |
echo ${cli} | |
echo -n ${cli} | pclip | |
} | |
function ffr { | |
local cli=`baseff relfile $*` | |
echo ${cli} | |
echo -n ${cli} | pclip | |
} | |
# find a file and copy its *nix direcotry (without filename) into clipboard | |
# cd into that directory at the same time | |
function ffcd() | |
{ | |
local cli=`baseff file $*` | |
if [ -z "${cli}" ]; then | |
echo "Nothing found!" | |
else | |
local dir=$(dirname "${cli}") | |
cd ${dir} && echo ${dir} | |
echo -n ${cli} | pclip | |
fi | |
} | |
# find&cd a directory. Copy its full path into clipboard | |
function zz() | |
{ | |
local cli=`baseff dir $*` | |
if [ -z "${cli}" ];then | |
echo "Nothing found!" | |
else | |
echo ${cli} | |
cd ${cli} | |
echo -n ${cli} | pclip | |
fi | |
} | |
function zzz() { | |
cd $HOME && zz | |
} | |
# same as ff but we get windows path | |
function cf() | |
{ | |
local cli=`baseff file $*` | |
local p=`cygpath -w $cli` | |
echo ${p} | |
echo -n ${p} | pclip; | |
} | |
# same as ffcd but we get windows path | |
function cfcd() | |
{ | |
local cli=`baseff file $*` | |
local dir=$(dirname "${cli}") | |
local p=`cygpath -w $dir` | |
cd ${dir} && echo ${p} | |
echo -n ${p} | pclip; | |
} | |
# read path from pipe and convert to cygwin path | |
function cyp() { | |
read cp; | |
local p=`cygpath -w $cp` | |
echo ${p} | |
echo -n ${p} | pclip; | |
} | |
# usage `find -name '*.txt' | sedi matched replaced` | |
function sedi() { | |
read cp; | |
echo $cp | xargs sed -i 's%'$1'%'$2'%g' | |
echo 'replace $1 with $2 done!' | |
} | |
function cuttail() # Cut last n lines in file, 10 by default. | |
{ | |
nlines=${2:-10} | |
sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1 | |
} | |
function lowercase() # move filenames to lowercase | |
{ | |
for file ; do | |
filename=${file##*/} | |
case "$filename" in | |
*/*) dirname==${file%/*} ;; | |
*) dirname=.;; | |
esac | |
nf=$(echo $filename | tr A-Z a-z) | |
newname="${dirname}/${nf}" | |
if [ "$nf" != "$filename" ]; then | |
mv "$file" "$newname" | |
echo "lowercase: $file --> $newname" | |
else | |
echo "lowercase: $file not changed." | |
fi | |
done | |
} | |
function swap() # swap 2 filenames around | |
{ | |
local TMPFILE=tmp.$$ | |
mv "$1" $TMPFILE | |
mv "$2" "$1" | |
mv $TMPFILE "$2" | |
} | |
# finds directory sizes and lists them for the current directory | |
dirsize () | |
{ | |
du -shx * .[a-zA-Z0-9_]* 2> /dev/null | \ | |
egrep '^ *[0-9.]*[MG]' | sort -n > /tmp/list | |
egrep '^ *[0-9.]*M' /tmp/list | |
egrep '^ *[0-9.]*G' /tmp/list | |
rm -rf /tmp/list | |
} | |
## | |
# Process/system related functions: | |
## | |
function my_ps() | |
{ ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; } | |
function pp() | |
{ my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; } | |
# This function is roughly the same as 'killall' on linux | |
# but has no equivalent (that I know of) on Solaris | |
function killps() # kill by process name | |
{ | |
local pid pname sig="-TERM" # default signal | |
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then | |
echo "Usage: killps [-SIGNAL] pattern" | |
return; | |
fi | |
if [ $# = 2 ]; then sig=$1 ; fi | |
for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do | |
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid ) | |
if ask "Kill process $pid <$pname> with signal $sig?" | |
then kill $sig $pid | |
fi | |
done | |
} | |
function myinfo() # get current host related info | |
{ | |
echo -e "\nYou are logged on ${MAGENTA}$HOST" | |
echo -e "\nAdditionnal information:$RESET " ; uname -a | |
echo -e "\n${MAGENTA}Users logged on:$RESET " ; w -h | |
echo -e "\n${MAGENTA}Current date :$RESET " ; date | |
echo -e "\n${MAGENTA}Machine stats :$RESET " ; uptime | |
echo -e "\n${MAGENTA}Memory stats :$RESET " ; free | |
echo -e "\n${MAGENTA}Local IP Address :$RESET" ; myip | |
echo | |
} | |
# Misc utilities: | |
function repeat() # repeat n times command | |
{ | |
local i max | |
max=$1; shift; | |
for ((i=1; i <= max ; i++)); do # --> C-like syntax | |
eval "$@"; | |
done | |
} | |
function ask() | |
{ | |
echo -n "$@" '[y/n] ' ; read ans | |
case "$ans" in | |
y*|Y*) return 0 ;; | |
*) return 1 ;; | |
esac | |
} | |
#======================================================================= | |
# | |
# PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04 | |
# Most are taken from the bash 2.05 documentation and from Ian McDonalds | |
# 'Bash completion' package | |
# (http://www.caliban.org/bash/index.shtml#completion) | |
# You will in fact need bash-2.05a for some features | |
# | |
#======================================================================= | |
if [ "${BASH_VERSION%.*}" \< "2.05" ]; then | |
echo "You will need to upgrade to version 2.05 for programmable completion" | |
return | |
fi | |
set +o nounset # otherwise some completions will fail | |
complete -A hostname rsh rcp telnet rlogin r ftp ping disk | |
complete -A export printenv | |
complete -A variable export local readonly unset | |
complete -A enabled builtin | |
complete -A alias alias unalias | |
complete -A function function | |
complete -A user su mail finger | |
complete -A helptopic help # currently same as builtins | |
complete -A shopt shopt | |
complete -A stopped -P '%' bg | |
complete -A job -P '%' fg jobs disown | |
complete -A directory mkdir rmdir | |
complete -A directory -o default cd | |
# Compression | |
complete -f -o default -X '*.+(zip|ZIP)' zip | |
complete -f -o default -X '!*.+(zip|ZIP)' unzip | |
complete -f -o default -X '*.+(z|Z)' compress | |
complete -f -o default -X '!*.+(z|Z)' uncompress | |
complete -f -o default -X '*.+(gz|GZ)' gzip | |
complete -f -o default -X '!*.+(gz|GZ)' gunzip | |
complete -f -o default -X '*.+(bz2|BZ2)' bzip2 | |
complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2 | |
# Postscript,pdf,dvi..... | |
complete -f -o default -X '!*.ps' gs ghostview ps2pdf ps2ascii | |
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype | |
complete -f -o default -X '!*.pdf' acroread pdf2ps zathura | |
complete -f -o default -X '!*.+(pdf|ps)' gv | |
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf | |
complete -f -o default -X '!*.tex' tex latex slitex | |
complete -f -o default -X '!*.lyx' lyx | |
complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps w3m | |
# Multimedia | |
complete -f -o default -X '!*.+(jp*g|gif|xpm|png|bmp)' xv gimp | |
complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321 | |
complete -f -o default -X '!*.+(ogg|OGG)' ogg123 | |
complete -f -o default -X '!*.pl' perl perl5 | |
# This is a 'universal' completion function - it works when commands have | |
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a' | |
_get_longopts () | |
{ | |
$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \ | |
grep ^"$2" |sort -u ; | |
} | |
_longopts_func () | |
{ | |
case "${2:-*}" in | |
-*) ;; | |
*) return ;; | |
esac | |
case "$1" in | |
\~*) eval cmd="$1" ;; | |
*) cmd="$1" ;; | |
esac | |
COMPREPLY=( $(_get_longopts ${1} ${2} ) ) | |
} | |
complete -o default -F _longopts_func configure bash | |
complete -o default -F _longopts_func wget id info a2ps ls recode | |
_make_targets () | |
{ | |
local mdef makef gcmd cur prev i | |
COMPREPLY=() | |
cur=${COMP_WORDS[COMP_CWORD]} | |
prev=${COMP_WORDS[COMP_CWORD-1]} | |
# if prev argument is -f, return possible filename completions. | |
# we could be a little smarter here and return matches against | |
# `makefile Makefile *.mk', whatever exists | |
case "$prev" in | |
-*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;; | |
esac | |
# if we want an option, return the possible posix options | |
case "$cur" in | |
-) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;; | |
esac | |
# make reads `makefile' before `Makefile' | |
if [ -f makefile ]; then | |
mdef=makefile | |
elif [ -f Makefile ]; then | |
mdef=Makefile | |
else | |
mdef=*.mk # local convention | |
fi | |
# before we scan for targets, see if a makefile name was specified | |
# with -f | |
for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do | |
if [[ ${COMP_WORDS[i]} == -*f ]]; then | |
eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion | |
break | |
fi | |
done | |
[ -z "$makef" ] && makef=$mdef | |
# if we have a partial word to complete, restrict completions to | |
# matches of that word | |
if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi | |
# if we don't want to use *.mk, we can take out the cat and use | |
# test -f $makef and input redirection | |
COMPREPLY=( $(cat $makef 2>/dev/null | \ | |
awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' \ | |
| tr -s ' ' '\012' | sort -u | eval $gcmd ) ) | |
} | |
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake | |
_killall () | |
{ | |
local cur prev | |
COMPREPLY=() | |
cur=${COMP_WORDS[COMP_CWORD]} | |
# get a list of processes (the first sed evaluation | |
# takes care of swapped out processes, the second | |
# takes care of getting the basename of the process) | |
COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \ | |
sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \ | |
awk '{if ($0 ~ /^'$cur'/) print $0}' )) | |
return 0 | |
} | |
complete -F _killall killall killps | |
# A meta-command completion function for commands like sudo(8), which | |
# need to first complete on a command, | |
# then complete according to that command's own | |
# completion definition - currently not quite foolproof | |
# (e.g. mount and umount don't work properly), | |
# but still quite useful -- | |
# By Ian McDonald, modified by me. | |
_my_command() | |
{ | |
local cur func cline cspec | |
COMPREPLY=() | |
cur=${COMP_WORDS[COMP_CWORD]} | |
if [ $COMP_CWORD = 1 ]; then | |
COMPREPLY=( $( compgen -c $cur ) ) | |
elif complete -p ${COMP_WORDS[1]} &>/dev/null; then | |
cspec=$( complete -p ${COMP_WORDS[1]} ) | |
if [ "${cspec%%-F *}" != "${cspec}" ]; then | |
# complete -F <function> | |
# | |
# COMP_CWORD and COMP_WORDS() are not read-only, | |
# so we can set them before handing off to regular | |
# completion routine | |
# set current token number to 1 less than now | |
COMP_CWORD=$(( $COMP_CWORD - 1 )) | |
# get function name | |
func=${cspec#*-F } | |
func=${func%% *} | |
# get current command line minus initial command | |
cline="${COMP_LINE#$1 }" | |
# split current command line tokens into array | |
COMP_WORDS=( $cline ) | |
$func $cline | |
elif [ "${cspec#*-[abcdefgjkvu]}" != "" ]; then | |
# complete -[abcdefgjkvu] | |
#func=$( echo $cspec | sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' ) | |
func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' ) | |
COMPREPLY=( $( eval compgen $func $cur ) ) | |
elif [ "${cspec#*-A}" != "$cspec" ]; then | |
# complete -A <type> | |
func=${cspec#*-A } | |
func=${func%% *} | |
COMPREPLY=( $( compgen -A $func $cur ) ) | |
fi | |
else | |
COMPREPLY=( $( compgen -f $cur ) ) | |
fi | |
} | |
#mkdir, cd into it | |
mkcd () { | |
mkdir -p "$*" | |
cd "$*" | |
} | |
complete -o default -F _my_command nohup exec eval \ | |
trace truss strace sotruss gdb | |
complete -o default -F _my_command command type which man nice | |
function myip() # get IP adresses | |
{ | |
local myip=`w3m -dump http://checkip.dyndns.org:8245/` | |
echo "${myip}" | |
} | |
function serverip() { | |
local ip=`dropbox_uploader.sh download myip.txt /tmp/myip.txt > /dev/null && cat /tmp/myip.txt` | |
echo "${ip}" | |
echo "${ip}"|pclip | |
} | |
#backup linux system | |
function bksys(){ | |
echo "HINT: backup file could be myarchlinux-'date +%Y%m%d-%H%M'.tgz" | |
#my home directory is already backed up, so I don't need archive it now | |
echo "BACKUP: tar zcvpf mylinux.tgz --exclude=/proc/* --exclude=/lost+found --exclude='mylinux.tgz' --exclude=/mnt/* --exclude=/home/cb/* --exclude=/sys/* /" | |
echo "RESTORE: 'tar zxvpf mylinux.tgz -C /' to restore system" | |
echo "http://i.linuxtoy.org/docs/guide/ch31s11.html for grub fstab xorg.conf" | |
} | |
function nosl(){ | |
if [ -z "$1" ]; then | |
echo "Usage: echo /hello/world|nosl num" | |
echo "strip num leading slashes" | |
else | |
perl -pe "\$n=$1;while(\$n>0){ \$_=~ s/[^\\\\\\/]*[\\\\\\/]+//;\$n--; }" | |
fi | |
} | |
function bbdbclean(){ | |
sed -i.bak '/\["" ""/d' $HOME/.bbdb | |
} | |
#https://github.com/clvv/fasd | |
if test -n "`type -t fasd`"; then | |
eval "$(fasd --init auto)" | |
alias d='fasd_cd -id' | |
alias f='fasd -if' | |
function rr { | |
local cli=`fasd -if` | |
echo ${cli} | |
echo -n ${cli} | pclip | |
} | |
fi | |
function csssize() { | |
if [ -z "$1" ]; then | |
echo "Usage: csssize test.png" | |
echo "create css from image file, imagemagic" | |
else | |
identify -format "%[w] %[h]" $1 |sed -e "s/\(.*\) \(.*\)/width:\1px;\nheight:\2px;/g" | |
fi | |
} | |
# {{ subversion stuff | |
# go to root directory of subversion | |
# support only subversion 1.7+ | |
function cdsr() | |
{ | |
grandparent="." | |
cnt=0 | |
while [ ! -d "$grandparent/.svn" ] && [ $cnt -lt 32 ] ; do | |
grandparent="$grandparent/.." | |
cnt=$[cnt + 1] | |
done | |
if [ ! -z "$grandparent" ]; then | |
cd $grandparent | |
if [ ${#PWD} -lt ${#HOME} ]; then | |
cd - | |
fi | |
else | |
echo "cannot find svn root diectory" | |
fi | |
} | |
# }} | |
alias crontabe="EDITOR='emacs -nw' crontab -e" | |
alias fehphotos="find -name '*.jpg' -o -name '*.JPG' -print0 | xargs -0 feh -d -F" | |
alias fehall="find -name '*.jpg' -o -name '*.JPG' -o -name '*.png' -o -name '*.PNG' -o -name '*.gif' -o -name '*.GIF' -o -name '*.xpm' -print0 | xargs -0 feh -d -F" | |
#@see https://github.com/dattanchu/pymodoro | |
alias timer='~/.pymodoro/pymodoro.py|dzen2' | |
# just bonus, sed -i 's/hello/hi/g;s/bye/c u/g' my.conf, to replace two variables in one sed cli | |
alias line2clip="perl -ne 'chomp and print'|pclip" | |
if [ "$OS_NAME" = "Darwin" ]; then | |
alias zcat='gunzip -c' #zcat is in POSIX mode and will append .Z to the file name | |
export PATH=/usr/local/bin:/usr/local/sbin:$PATH #brew install packages shoud run first | |
if [ -d /Applications/LibreOffice.app/Contents/share/extensions/dict-en ]; then | |
export DICPATH=/Applications/LibreOffice.app/Contents/share/extensions/dict-en | |
fi | |
fi | |
#set up env for different machines | |
if [ -f "$HOME/.bashrc.local" ]; then | |
. "$HOME/.bashrc.local" >/dev/null | |
fi | |
alias ca='echo $((`date +"%m"`+1)) `date +"%Y"` | xargs cal -3' | |
alias mywatch="watch -tn 1 date +%T \|figlet -c -t -W" | |
function big() { | |
# find files and sort by size, full path is printed | |
find -name "$*" -type f -printf "`pwd`%P %s\n"|sort -k2,2n | |
} | |
function parse_git_branch() { | |
git rev-parse --abbrev-ref HEAD 2>/dev/null | |
} | |
# {{ @see http://unix.stackexchange.com/questions/14303/bash-cd-up-until-in-certain-folder/14311#14311 | |
upto () | |
{ | |
if [ -z "$1" ]; then | |
return | |
fi | |
local upto=$1 | |
cd "${PWD/\/$upto\/*//$upto}" | |
} | |
# auto-completion in bash | |
function _upto() | |
{ | |
local cur=${COMP_WORDS[COMP_CWORD]} | |
local d=${PWD//\//\ } | |
COMPREPLY=( $( compgen -W "$d" -- "$cur" ) ) | |
} | |
complete -F _upto upto | |
# In addition, I have another function jd which allows me to jump to any directory below the current one: | |
function jd() { | |
if [ -z "$1" ]; then | |
echo "Usage: jd [directory]"; | |
return 1 | |
else | |
cd **"/$1" | |
fi | |
} | |
# }} | |
# {{ toggle coporate proxy | |
# @see http://stackoverflow.com/questions/21705091/bower-behind-a-proxy | |
function set_proxy() { | |
export HTTP_PROXY=http://127.0.0.1:3128 | |
export HTTPS_PROXY=http://127.0.0.1:3128 | |
# some tools uses lowercase env variables | |
export http_proxy=http://127.0.0.1:3128 | |
export https_proxy=http://127.0.0.1:3128 | |
# config git | |
git config --global http.proxy http://127.0.0.1:3128 | |
git config --global https.proxy http://127.0.0.1:3128 | |
git config --global url."http://".insteadOf git:// | |
} | |
function unset_proxy() { | |
unset HTTP_PROXY | |
unset HTTPS_PROXY | |
unset http_proxy | |
unset https_proxy | |
git config --global --unset http.proxy | |
git config --global --unset https.proxy | |
git config --global --unset url."http://".insteadOf | |
} | |
function vidrmseg() { | |
# Usage: | |
# vidrmseg test.mp4 48 93 # remove video between sec 48 and sec 93 | |
# vidrmseg test.mp4 48 # remove video after 48 | |
local f=${1%.*} | |
local ext=${1##*.} | |
if [ -z "$3" ]; then | |
ffmpeg -y -i $1 -filter_complex "[0:v]trim=duration=${2}[a]" -map [a] ${f}.copy.${ext} | |
else | |
ffmpeg -y -i $1 -filter_complex "[0:v]trim=duration=${2}[a];[0:v]trim=start=${3},setpts=PTS-STARTPTS[b];[a][b]concat[c]" -map [c] ${f}.copy.${ext} | |
fi | |
} | |
# @see https://rudd-o.com/linux-and-free-software/tales-from-responsivenessland-why-linux-feels-slow-and-how-to-fix-that | |
function enough_memory() { | |
# change /etc/sysctl.conf to make it permanent | |
sudo sysctl -w vm.swappiness=1 | |
sudo sysctl -w vm.vfs_cache_pressure=10 | |
} | |
function video2mp3 () { | |
if [ -z $1 ]; then | |
echo "Usage: video2mp3 filename [start_second] [total_second]" | |
echo "For example, video2mp3 1.mp4 5 10" | |
return; | |
fi | |
# set gif width | |
if [ -z $2 ]; then | |
local start=0 | |
else | |
local start=$2 | |
fi | |
if [ -z $2 ]; then | |
local total=5 | |
else | |
local total=$3 | |
fi | |
ffmpeg -i "$1" -vn -ss $start -t $total -acodec copy "${1%%.*}-$start-$total.mp3" | |
} | |
function video2gif () { | |
if [ -z $1 ]; then | |
echo "Usage: video2gif filename [width]" | |
return; | |
fi | |
# set gif width | |
if [ -z $2 ]; then | |
local width=320 | |
else | |
local width=$2 | |
fi | |
local palette="/tmp/palette.png" | |
local filters="fps=15,scale=$width:-1:flags=lanczos" | |
if [ -f $1 ]; then | |
ffmpeg -i $1 -vf "$filters,palettegen" -y $palette | |
ffmpeg -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y ${1%%.*}.gif | |
echo "${1%%.*}.gif is created." | |
else | |
echo "File $1 does NOT exist!" | |
fi | |
} | |
function audio2video { | |
# Add audio to video using ffmpeg | |
# @see https://superuser.com/questions/590201/add-audio-to-video-using-ffmpeg | |
if [ -z $1 ]; then | |
echo "Usage: audio2video 1.mp4" | |
return; | |
fi | |
ffmpeg -i $1 -i ${1%%.*}.mp3 -c copy -map 0:v:0 -map 1:a:0 new-$1 | |
mv new-$1 $1 | |
} | |
function video-rotate-resize { | |
if [ -z $1 ]; then | |
echo "Usage: video-rotate-resize 1.mp4" | |
return; | |
fi | |
ffmpeg -i $1 -vf "transpose=1" -filter:v scale=640:-1 new-${1%%.*}.mp4 | |
mv new-${1%%.*}.mp4 ${1%%.*}.mp4 | |
} | |
function video-resize { | |
if [ -z $1 ]; then | |
echo "Usage: video-resize 1.mp4" | |
return; | |
fi | |
ffmpeg -i $1 -filter:v scale=640:-1 new-${1%%.*}.mp4 | |
mv new-${1%%.*}.mp4 ${1%%.*}.mp4 | |
} | |
# https://stackoverflow.com/questions/9679932/how-to-use-package-installed-locally-in-node-modules | |
alias npmbin='PATH=$(npm bin):$PATH' | |
export PS1="\[${BOLD}${MAGENTA}\]\u\[$RESET\]@\[$ORANGE\]\h\[$RESET\]:\[$GREEN\]\w\[$RESET\]\$(echo \" on \")\[$PURPLE\]\$(parse_git_branch)\[$RESET\]\n\[$RESET\]\$ " | |
export PS2="\[$ORANE\]->\[$RESET\]" | |
# @see https://github.com/mathiasbynens/dotfiles/blob/master/.bash_profile | |
# Add tab completion for SSH hostnames based on ~/.ssh/config, ignoring wildcards | |
[ -e "$HOME/.ssh/config" ] && complete -o "default" -o "nospace" -W "$(grep "^Host" ~/.ssh/config | grep -v "[?*]" | cut -d " " -f2 | tr ' ' '\n')" scp sftp ssh | |
# bash completion | |
bind "set completion-ignore-case on" | |
bind "set show-all-if-ambiguous on" | |
bind "set page-completions off" | |
bind "set show-all-if-unmodified on" | |
bind "set completion-query-items -1" | |
# {{ perl local libs | |
PATH="$HOME/perl5/bin${PATH:+:${PATH}}"; export PATH; | |
PERL5LIB="$HOME/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB; | |
PERL_LOCAL_LIB_ROOT="$HOME/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT; | |
PERL_MB_OPT="--install_base \"$HOME/perl5\""; export PERL_MB_OPT; | |
PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"; export PERL_MM_OPT; | |
# }} | |
# {{ python | |
if [ -d $HOME/.virtualenvs ]; then | |
export WORKON_HOME=$HOME/.virtualenvs | |
fi | |
if [ -x /usr/bin/python3 ]; then | |
# safer than `ln -s /usr/bin/python3 /usr/bin/python' | |
alias python="/usr/bin/python3" | |
fi | |
# }} | |
# @see https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html | |
export GPG_TTY=$(tty) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment