## -*- mode:sh -*- # ################################################################################ ## Shell -- Functions. ## Date 2012-08-11 ################################################################################ ## Colored man pager. 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 "$@" } ## Make directories and change into the first one. mkcd () { mkdir -p "$@" cd "$1" } ## Quick search. search() { find . -iname "*$1*" } ## Cut last n lines in file, 10 by default. cuttail() { local nlines=${2:-10} sed -n -e ":begin ; 1,${nlines}!{P;N;D} ; N ; b begin" $1 } ## Cut first n lines in file, 10 by default. cuthead() { local nlines=${2:-10} sed -n -e "1,${nlines}!p" $1 } ## Move filenames to lowercase. ## Use ranger + bulkrename + vim/emacs (+ TwindleCase) for more flexibility. renamelower() { local file local filename local dirname for file ; do filename=${file##*/} case "$filename" in */*) dirname="${file%/*}" ;; *) dirname="." ;; esac local nf=$(echo $filename | tr A-Z a-z) local newname="${dirname}/${nf}" if [ "$nf" != "$filename" ]; then mv "$file" "$newname" echo "lowercase: $file --> $newname" else echo "lowercase: $file not changed." fi done } ## Swap 2 filenames around. renameswap() { local TEMPFILE="$(mktemp)" mv "$1" "$TEMPFILE" mv "$2" "$1" mv "$TEMPFILE" "$2" } ## Finds directory sizes and lists them for the current directory. dirsize () { local TEMPFILE="$(mktemp)" # du -shx * 2> /dev/null | \ du -shx * .[a-zA-Z0-9_]* 2> /dev/null | \ egrep '^ *[0-9.]*[MG]' | sort -n > "${TEMPFILE}" egrep '^ *[0-9.]*M' "${TEMPFILE}" egrep '^ *[0-9.]*G' "${TEMPFILE}" rm -rf "${TEMPFILE}" } ## Network operations if [ -e "/usr/bin/nmap" ]; then network-map() { echo "$1" for SCANIP in $( nmap -sL "$1" | grep -i "\([[:digit:]]\+\.\)\{3,\}[[:digit:]]\+" | awk '{print $5}' ); do sudo nmap -oX - -n -sT -T Normal -O -sR -I -F -P0 "$SCANIP" echo done } fi ## Vim-only: search the vim reference manual for a keyword. ## Usage: :h if [ -e "/usr/bin/vim" ]; then :h() { vim --cmd ":silent help $@" --cmd "only"; } fi ## Set file/directory owner and permissions. ## Usage: sanitize [FOLDER] sanitize() { local WORKDIR="$PWD" if [ $# -eq 1 ]; then WORKDIR="$1" fi local FMASK=$(umask -S | sed 's/x//g') local DMASK=$(umask -S) find "$WORKDIR" -exec chown -R ${UID}:${GID} {} \; find "$WORKDIR" -type d -exec chmod ${DMASK} {} \; find "$WORKDIR" -type f -exec chmod ${FMASK} {} \; } asciify() { asciify_help() { echo echo "Usage:" echo -e "\t$1 FILES" echo echo "Synopsis:" echo -e "\tConvert non-ASCII characters to their ASCII equivalent." echo } if [ $# -eq 0 ]; then echo "Missing arguments." asciify_help $0 return fi for i; do sed -i \ -e 's/[àáâä]/a/g' \ -e 's/[éèêë]/e/g' \ -e 's/[ïîí]/i/g' \ -e 's/[öôó]/o/g' \ -e 's/[ùúûü]/u/g' \ -e 's/[À]/A/g' \ -e 's/[ÉÈ]/E/g' \ -e 's/[ñ]/n/g' \ -e 's/[œ]/oe/g' \ -e 's/[Œ]/Oe/g' \ -e 's/[æ]/ae/g' \ -e 's/[Æ]/Ae/g' \ -e 's/[ç]/c/g' \ -e 's/[Ç]/C/g' \ "$i" done; } blind-append() { blind_help() { echo echo "Usage:" echo -e "\t$1 FILE [STRING]" echo echo "Synopsis:" echo -e "\tAppend to all STRING found in FILE a secret phrase being prompted." echo -e "\tIf STRING is omitted, secret phrase will be appended to the end of the file." echo -e "\tIf FILE does not exist, it will be created and secret phrase will be inserted. STRING will be ignored." echo } if [ $# -gt 2 ] || [ $# -lt 1 ]; then echo "Wrong number of arguments." blind_help $0 return fi local FILE="$1" local STRING="" local DUMMY if [ $# -eq 2 ]; then STRING="$2" fi echo -n "Secret: " read -s DUMMY echo "" if [ ! -e "$FILE" ] || [ "$STRING" = "" ]; then echo "$DUMMY" >> "$FILE" echo "Secret appended to ${FILE} at the end." return fi if [ $# -eq 1 ]; then echo "$DUMMY" >> "$FILE" else sed -i "s/${STRING}/${STRING}${DUMMY}/g" "${FILE}" fi echo "Secret appended to ${FILE}." return } ## Term properties termcolors256() { x=$(tput op) y=$(printf %76s) for i in {0..256}; do o=00$i echo -e "${o:${#o}-3:3} $(tput setaf $i;tput setab $i)${y// /=}$x" done } termcolors() { # The test text. Must be 3 letters. T='Doh' echo -e "\n 40m 41m 42m 43m\ 44m 45m 46m 47m"; for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \ '1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \ ' 36m' '1;36m' ' 37m' '1;37m'; do FG=${FGs// /} echo -en " $FGs \033[$FG $T " for BG in 40m 41m 42m 43m 44m 45m 46m 47m; do echo -en "$EINS \033[$FG\033[$BG $T \033[0m"; done echo; done echo } termprop() { infocmp -1 | sed -nu 's/^[ \000\t]*//;s/[ \000\t]*$//;/[^ \t\000]\{1,\}/!d;/acsc/d;s/=.*,//p'| column -c80 } termsupport() { for T in `find "/usr/share/terminfo" -type f -printf '%f\n'`;do echo "$T `tput -T $T colors`" done | sort -nk2 } ## Highlight themes viewer for 256-colors terminals. if [ -f "/usr/bin/highlight" ] ; then hlt-viewer () { print_help() { echo "Synopsis:" echo -e " $1" echo echo "This script displays a preview for every highlight's theme." echo "Press ENTER to display next preview. Press anything else then ENTER to quit." } if [ $# -gt 0 ]; then print_help "$0" return fi local LIST=$(highlight -w | grep -v "\s\|^$") local SAMPLE="void function(char* pointer, int &ref) { int integer=3; char* string=\"Hello!\"; // Line comment for ( i=0; i<10; i++) { printf(\"Sum: %d\\\n\", i*( integer+14 ) ); } }" unset DUMMY for i in $(highlight -w | grep -v "\s\|^$"); do echo "******************** $i ********************" highlight -S c -O xterm256 <(echo $SAMPLE) -s "$i" read -s DUMMY if [ ! "$DUMMY" = "" ];then return fi done } fi ## Extractor -- Useless when using 'atool'. if [ ! -e "/usr/bin/atool" ]; then extract () { if [ -f $1 ] ; then case $1 in *.tar.bz2) tar xvjf $1 ;; *.tar.gz) tar xvzf $1 ;; *.tar.xz) tar xvJf $1 ;; *.bz2) bunzip2 $1 ;; *.rar) unrar x $1 ;; *.gz) gunzip $1 ;; *.tar) tar xvf $1 ;; *.tbz2) tar xvjf $1 ;; *.tgz) tar xvzf $1 ;; *.zip) unzip $1 ;; *.Z) uncompress $1 ;; *.7z) 7z x $1 ;; *.xz) unxz $1 ;; *.exe) cabextract $1 ;; *) echo "\`$1': unrecognized file compression" ;; esac else echo "\`$1' is not a valid file" fi } fi # Warning: use this function with caution. It may drastically improve # compression of some PDF files, but in some case, the output filesize will be # greater! You should not use it over PDF files embedding pictures as well. pdfcompress () { if [ $# -lt 1 -o $# -gt 2 ]; then echo "Usage: pdfcompress PDFFILE [DESTFILE]" return fi if [ ! -f "$1" ]; then echo "$1 is not a valid PDF file!" fi local INPUTFILE="$1" if [ -z "$2" ]; then gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="${INPUTFILE%%.*}-COMPRESSED.pdf" "${INPUTFILE}" rm -rf "${INPUTFILE}" mv "${INPUTFILE%%.*}-COMPRESSED.pdf" "${INPUTFILE}" else local OUTPUTFILE="$2" gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="${OUTPUTFILE}" "${INPUTFILE}" fi } ## Create an archive from a single or multiples files/folders. archive () { printhelp() { echo "Synopsis:" echo -e " $1 [-m METHOD] [-v] FILE" echo echo "Usage:" echo -e " default:\tDisplay packages included in FILE but not installed." echo -e " -h:\t\tDisplay this help." echo -e " -m:\t\tChoose compression method." echo -e " gz\t\tgzip (default)." echo -e " xz\t\tLZMA." echo -e " -v:\t\tInclude VCS data." } local OPTION_VCS="--exclude-vcs" local OPTION_METHOD="" while getopts ":hm:v" opt; do case $opt in h) printhelp "$0" return 1 ;; m) OPTION_METHOD="${OPTARG}" ;; v) OPTION_VCS="" ;; ?) printhelp "$0" return 1 ;; :) echo "Missing argument." echo "Use $0 -h for help." return 1 ;; esac done local ARCEXT local ARCOPT case $OPTION_METHOD in "gz") ARCEXT="tar.gz" ARCOPT="z" ;; "xz") ARCEXT="tar.xz" ARCOPT="J" ;; *) ARCEXT="tar.gz" ARCOPT="z" ;; esac shift $(($OPTIND - 1)) if [ $# -eq 0 ]; then echo "Missing argument." echo "Use $0 -h for help." return 1 fi local ARCPATH local ARCSOURCE local ARCNAME if [ $# -eq 1 ]; then ARCPATH="$(dirname $(readlink -f "$1"))" ARCSOURCE="$(basename $(readlink -f "$1"))" ARCNAME="${ARCSOURCE}-$(date +%y-%m-%d-%H%M%S).${ARCEXT}" (cd "$ARCPATH" && \ tar -${ARCOPT} -cvf "$ARCNAME" "$ARCSOURCE" ${OPTION_VCS}) else ARCSOURCE="$(basename $PWD)" ARCNAME="$(basename "$ARCSOURCE")-$(date +%y-%m-%d-%H%M%S).${ARCEXT}" if [ $# = 0 ];then (cd "$PWD/.." && \ tar -${ARCOPT} -cvf "$ARCNAME" "$ARCSOURCE" ${OPTION_VCS}) else local FILELIST=() for i; do FILELIST=(${FILELIST[*]} "$i") done tar -${ARCOPT} -cvf "$ARCNAME" ${FILELIST[*]} ${OPTION_VCS} fi fi } ## Git compare git-compare() { if [ $# -ne 1 ]; then echo "Wrong number of argument." return fi comm -3 <(git ls-files | sort) <(find "$1" -type f | sed 's/^[^\/]*\///g' | sort) } ## This function will clean TeX/LaTeX project folders recursively. texclean () { if [ -z "$1" ]; then WORKDIR="$PWD" else WORKDIR="$1" fi find "$WORKDIR" -type f \( \ -name "*.aux" -o \ -name "*.idx" -o \ -name "*.ilg" -o \ -name "*.ind" -o \ -name "*.lof" -o \ -name "*.log" -o \ -name "*.nav" -o \ -name "*.out" -o \ -name "*.snm" -o \ -name "*.tns" -o \ -name "*.toc" \) \ -print \ -delete } ## Clean current folder vcsclean() { local WORKDIR if [ -z "$1" ]; then WORKDIR="$PWD" else WORKDIR="$1" fi local CHOICE echo "This will clean current folder from all VCS control files." echo -n "Proceed ? [y/N] " while [ -z "$CHOICE" ]; do read CHOICE done CHOICE=$(echo $CHOICE | tr '[:upper:]' '[:lower:]') if [ "$CHOICE" = "y" ]; then find "$WORKDIR" -type d \( \ -name ".bzr" -o \ -name ".cvs" -o \ -name ".git" -o \ -name ".hg" -o \ -name ".svn" \) \ -print \ -delete echo "VCS files cleaned." fi } ## LSOF stats. Print number of open files per process. lsofstat() { local LSOFOUT=$(lsof|awk '{print $1}') for i in $(echo $LSOFOUT |sort -u);do echo -n "$i " echo $LSOFOUT | grep ^$i | wc -l done } ## Format C ## Consider indent, astyle, uncrustify. formatc() { if [ ! -e /usr/bin/indent ]; then echo "Please install 'indent'" return fi local WORKDIR if [ -z "$1" ]; then WORKDIR="$PWD" else WORKDIR="$1" fi find "$WORKDIR" -type f \ -name "*.[ch]" \ -print \ -exec indent -i4 -ppi4 -bli0 -cli4 -nut {} \; ## Remove backup files. find "$WORKDIR" -type f \( \ -name "*.[ch]~" -o \ -name "*.[ch]~[0-9]*~" \) \ -delete # ## Manual method. # ## Remove trailing whitespace # sed -i 's/\s*$//g' "$FILE" # ## Function parenthesis # sed -i 's/\([^ ]\)(/\1 (/g' "$FILE" # sed -i 's/\s\s\+(/ (/g' "$FILE" # ## Semicolon # sed -i 's/\([^ ]\);/\1 ;/g' "$FILE" # sed -i 's/;\([^ ]\)/; \1/g' "$FILE" # # Skip line -- Bad idea because of 'for' loops. # # sed -i 's/^\(\s*\)\(.*\);\s*\(.\+\)$/\1\2;\n\1\3/g' "$FILE" # ## Commas # sed -i 's/\s\s\+,/,/g' "$FILE" # sed -i 's/,\([^ ]\)/, \1/g' "$FILE" # ## Plus/Minus # sed -i 's/\([^+-]\)\([-+]\)\([^ +-]\)/\1\2 \3/g' "$FILE" # sed -i 's/\([^ +-]\)\([-+]\)\([^+-]\)/\1 \2\3/g' "$FILE" # sed -i 's/\( \+++\)/++/g' "$FILE" # sed -i 's/\(++ \+\)/++/g' "$FILE" # sed -i 's/\( \+--\)/--/g' "$FILE" # sed -i 's/\(-- \+\)/--/g' "$FILE" # ## Modulus, equality, affectation, binary ops, comparison # sed -i 's/\s\s\+\(%\|==\|&&\|||\|<=\|>=\|!=\)/ \1/g' "$FILE" # sed -i 's/\(%\|==\|&&\|||\|<=\|>=\|!=\)\s\s\+/\1 /g' "$FILE" # sed -i 's/\([^ ]\)\(%\|==\|&&\|||\|<=\|>=\|!=\)/\1 \2/g' "$FILE" # sed -i 's/\(%\|==\|&&\|||\|<=\|>=\|!=\)\([^ ]\)/\1 \2/g' "$FILE" # ## Equality, >, < # sed -i 's/\s\s\+\([<>=]\)/ \1/g' "$FILE" # sed -i 's/\([<>=]\)\s\s\+/\1 /g' "$FILE" # sed -i 's/\([<>=]\)\([^ =]\)/\1 \2/g' "$FILE" # sed -i 's/\([^ ]\)\([<>]\)/\1 \2/g' "$FILE" # sed -i 's/\([^ =<>]\)\(=\)/\1 \2/g' "$FILE" # ## Asterisk, slash # sed -i 's/\s\s\+\*/ \*/g' "$FILE" # sed -i 's/\*\s\s\+/\* /g' "$FILE" # sed -i 's/\([^\/]\)\/\s\+/\1\//g' "$FILE" # sed -i 's/\s\+\/\([^\/]\)/\/\1/g' "$FILE" # ## Braces # sed -i 's/^\( *\)\(.\+\) *{ *$/\1\2\n\1{/g' "$FILE" # ## Proper comments # sed -i 's:// *\([[:lower:]]\):// \u\1:g' "$FILE" # sed -i 's:\(//.*[^\.]\)$:\1\.:g' "$FILE" } ## This function will try to find an input binary file in the content of binary ## files in current folder. bindatasearch() { if [ $# -eq 0 ] || [ ! -f "$1" ]; then echo "Please provide a valid single file as argument." return fi ## Must be a folder. local TARGET=$PWD if [ $# -eq 2 ] && [ -d "$2" ]; then TARGET="$2" fi ## The awk command suppresses first column, spaces and line breaks. local SOURCE=$(od -tx8 "$1" | awk '($1="")1 gsub ( /\s/,"") { printf ("%s", $0) }') ## This special, not well-known syntax allows us to execute a set of ## functions of the result of find. Since everything MUST be between simple ## quotes, we cannot use external variables directly. So we pass the $SOURCE ## variable as argument. The underscore at the end allow the use of ## arguments. find "$WORKDIR" -type f -exec bash -c ' FILEDUMP=$(od -tx8 "$1" | awk '"'"'($1="")1 gsub ( /\s/,"") { printf ("%s", $0) }'"'"') grep -q "$2" <(echo $FILEDUMP) [ $? -eq 0 ] && echo "$1" ' _ {} "$SOURCE" \; } ## Xrandr xmulti () { if [ $# -ne 1 ]; then echo "Wrong number of argument." return fi xrandr --output "$1" --auto --right-of $(xrandr | sed -n "/current/{n;p;q}" | cut -f1 -d" ") } xmultioff () { if [ $# -ne 1 ]; then echo "Wrong number of argument." return fi xrandr --output "$1" --off } ##============================================================================== ## Pacman Functions ##============================================================================== if [ -f "/usr/bin/pacman" ]; then source "${SHELL_DIR}/funs_pacman" fi ##============================================================================== ## TeXlive functions ##============================================================================== ## TeXlive if [ -d "/usr/local/texlive" ]; then tli () { ## Warning: it is important to set umask properly, otherwise users might ## not have authorization to use the packages. ## TODO: It is dirty to invoke a subshell several times. ## Would be better to pass one parameter, then to tokenize it. for i ; do sudo bash -c 'umask 022 && tlmgr install "$0"' "$i" done } tls () { tlmgr search --global "$@" } fi