## -*- mode:sh -*- # ################################################################################ ## Shell -- Functions. ## Date 2012-06-21 ################################################################################ ## Make dir and go into it. mkcd () { mkdir -p "$*" cd "$*" } ## Quick search. search() { find . -iname "*$1*" } ## Cut last n lines in file, 10 by default. cuttail() { nlines=${2:-10} #sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1 head $1 -n$(($(cat $1|wc -l) - $nlines)) } ## Cut first n lines in file, 10 by default. cuthead() { nlines=${2:-10} tail $1 -n$(($(cat $1|wc -l) - $nlines)) } ## Move filenames to lowercase. ## Use ranger + bulkrename + vim/emacs (+ TwindleCase) for more interactivity. renamelower() { 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 } ## Swap 2 filenames around. renameswap() { local TMPFILE=tmp.$$ mv "$1" $TMPFILE mv "$2" "$1" mv $TMPFILE "$2" } ## Finds directory sizes and lists them for the current directory. dirsize () { TEMPFILE="$(mktemp)" # du -shx * .[a-zA-Z0-9_]* 2> /dev/null | \ du -shx * 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 networkmap() { 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 according to umask. ## Usage: sanitize FILE|FOLDER sanitize() { chown -R ${UID}:${GID} "$@" chmod -R $(umask -S) "$@" } 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 's/[àáâä]/a/g' "$i" sed -i 's/[éèêë]/e/g' "$i" sed -i 's/[ïîí]/i/g' "$i" sed -i 's/[öôó]/o/g' "$i" sed -i 's/[ùúûü]/u/g' "$i" sed -i 's/[À]/A/g' "$i" sed -i 's/[ÉÈ]/E/g' "$i" sed -i 's/[ñ]/n/g' "$i" sed -i 's/[œ]/oe/g' "$i" sed -i 's/[Œ]/Oe/g' "$i" sed -i 's/[æ]/ae/g' "$i" sed -i 's/[Æ]/Ae/g' "$i" sed -i 's/[ç]/c/g' "$i" sed -i '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 FILE="$1" STRING="" if [ $# -eq 2 ]; then STRING="$2" fi read -s DUMMY if [ ! -e "$FILE" ] || [ "$STRING" = "" ]; then echo "$DUMMY" >> "$FILE" echo "Secrect blindly 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 blindly appended to ${FILE}." return } ## Term properties termcolors(){ 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 } 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 } ## Start X and lock current terminal (press ENTER when back in terminal to prompt for password) if [ -e "/usr/bin/vlock" ]; then sx(){ startx & vlock } fi ## 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 "$@" } ## Highlight themes viewer for 256-colors terminals. 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 [ ! -f "/usr/bin/highlight" ];then echo "Please install 'highlight'." return fi if [ $# -gt 0 ]; then print_help "$0" return fi LIST=$(highlight -w | grep -v "\s\|^$") 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 } ## 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 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 OUTPUTFILE="$2" gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="${OUTPUTFILE}" "${INPUTFILE}" fi } # This function will clean TeX/LaTeX project folders recursively. function texclean () { if [ -z "$1" ]; then WORKDIR="$PWD" else WORKDIR="$1" fi find "$WORKDIR" \( \ -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" \) \ -exec echo {} \; \ -exec rm -f {} \; } ## Create an archive from a single or multiples files/folders. ## This archive archive-project () { if [ $# -eq 1 ]; then ARCPATH="$(dirname $(readlink -f "$1"))" ARCSOURCE="$(basename $(readlink -f "$1"))" ARCNAME="${ARCSOURCE}-$(date +%y-%m-%d-%H%M%S).tgz" (cd "$ARCPATH" && \ tar cvzf "$ARCNAME" "$ARCSOURCE" --exclude-vcs) else ARCSOURCE="$(basename $PWD)" ARCNAME="$(basename "$ARCSOURCE")-$(date +%y-%m-%d-%H%M%S).tgz" if [ $# = 0 ];then (cd "$PWD/.." && \ tar cvzf "$ARCNAME" "$ARCSOURCE" --exclude-vcs) else FILELIST=() for i; do FILELIST=(${FILELIST[*]} "$i") done tar cvzf "$ARCNAME" ${FILELIST[*]} --exclude-vcs fi fi } ## Clean current folder cleanvcs() { unset CHOICE echo "This will clean current folder from all VCS control files." echo -n "Proceed ? [y/N] " while [ -z "$CHOICE" ]; do # read 'Proceed [y/N] ' CHOICE read CHOICE done CHOICE=$(echo $CHOICE | tr '[:upper:]' '[:lower:]') if [ "$CHOICE" = "y" ]; then find . -type d -name ".svn" -exec rm -rf {} \; echo "VCS files cleaned." fi } ## LSOF stats. Print number of open files per process. lsofstat() { LSOFOUT=$(lsof|awk '{print $1}') for i in $(echo $LSOFOUT |sort -u);do echo -n "$i " echo $LSOFOUT | grep ^$i | wc -l done } ##============================================================================== ## Pacman Functions ##============================================================================== if [ -f "/usr/bin/pacman" ]; then ## TODO: completion does not work as is. It requires pacman arguments like -S or -Q. ## There should be a way to use it. # if isShell "zsh" ; then # compdef _pacman pacman-deps # elif isShell "bash"; then # complete -o default -o nospace -F _pacman pacman-deps # fi ## This function gets the pacman variabless when necessary. ## Note: some functions uses pacman localized output. It should work in any case. ## Note: you should always call _pacman_unset_vars in the end. _pacman_set_vars() { local pacman_var_list="$(pacman -Qi tzdata | cut -f1 -d':')" if [ "$pacman_var_list" = "" ];then echo "Could not get pacman's variables." return 2 fi pacman_name="$(echo "$pacman_var_list" | sed -n '1p')" pacman_deps="$(echo "$pacman_var_list" | sed -n '7p')" pacman_optdeps="$(echo "$pacman_var_list" | sed -n '8p')" pacman_size="$(echo "$pacman_var_list" | sed -n '12p')" } _pacman_unset_vars() { unset pacman_name unset pacman_deps unset pacman_optdeps unset pacman_size } ## Get detailed file size list for the specified packages. if [ -f "/usr/bin/pacman" ]; then pacman-files() { if [ $# -lt 1 ];then echo "Wrong number of arguments." return fi RESULT_HUMAN="$(du -bh $(pacman -Qlq "$@" | grep -v ".*/$" | sort -u))" RESULT="$(du -b $(pacman -Qlq "$@" | grep -v ".*/$" | sort -u))" echo "${RESULT_HUMAN}" echo "$RESULT" | awk -F "[[:alpha:]]" '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL/1024)}' } fi ## Retrieve official packages list. if [ -f "/usr/bin/pacman" ]; then pacman-official() { # Alternative 'diff' verision. # diff <(pacman -Qq | sort) <(pacman -Qmq | sort) --new-line-format='' --unchanged-group-format='%>' comm -3 <(pacman -Qq | sort) <(pacman -Qmq | sort) } fi ## Compare installed packages with list. if [ -f "/usr/bin/pacman" ]; then pacman-diff() { printhelp() { echo "Synopsis:" echo -e " $1 [-m|-e] [-q] FILE" echo echo "Usage:" echo -e " default:\tDisplay packages included in FILE but not installed." echo -e " -e:\t\tCompare FILE to explicitly installed packages." echo -e " -h:\t\tDisplay this help." echo -e " -m:\t\tCompare FILE to foreign installed packages." echo -e " -q:\t\tDisplay installed packages not included in FILE." } OPTION_EXPLICIT="" OPTION_FOREIGN="" OPTION_LOCAL="-1" while getopts ":hmqe" opt; do case $opt in e) OPTION_EXPLICIT="e" ;; h) printhelp "$0" return 1 ;; m) OPTION_FOREIGN="m" ;; q) OPTION_LOCAL="-2" ;; ?) printhelp "$0" return 1 ;; :) echo "Missing argument." echo "Use $0 -h for help." return 1 ;; esac done shift $(($OPTIND - 1)) if [ $# -eq 0 ]; then echo "Missing argument." echo "Use $0 -h for help." return 1 fi comm -3 ${OPTION_LOCAL} <(pacman -Qq${OPTION_FOREIGN}${OPTION_EXPLICIT} | sort) <(sort "$*") } fi ## Print specified package size and a grand total. if [ -f "/usr/bin/pacman" ]; then pacman-size() { printhelp() { echo "Synopsis:" echo -e " $1 [-a|-h|-n|-q] PACKAGES" echo -e " Arguments MUST be set before package list." echo echo "Usage:" echo -e " default:\tDisplay package size. Output contains no double and is alphabetically sorted. A grand total is printed at the end. It will only work for repos packages by default." echo -e " -h:\t\tShow this help." echo -e " -n:\t\tOutput is sorted by size.." echo -e " -q:\t\tUses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos." } CMD="pacman -Si" SEP=": " TOTAL_SIZE=0 SORT="sort -u -k3" SORT_SIZE="cat" while getopts ":hnq" opt; do case $opt in h) printhelp "$0" return 1 ;; n) SORT_SIZE="sort -n" ;; q) CMD="pacman -Qi" ;; ?) printhelp "$0" return 1 ;; :) echo "Missing argument." echo "Use $0 -h for help." return 1 ;; esac done shift $(($OPTIND - 1)) if [ $# -eq 0 ]; then echo "Missing argument." echo "Use $0 -h for help." return 1 fi _pacman_set_vars RESULT=$(eval "${CMD} $@ 2>/dev/null" | awk -F "$SEP" -v filter="$pacman_size" -v pkg="$pacman_name" \ '$0 ~ pkg {pkgname=$2} $0 ~ filter {gsub(/\..*/,"") ; printf("%6s KiB %s\n", $2, pkgname)}' | eval "$SORT" | eval "$SORT_SIZE") echo "$RESULT" ## Print total size. echo "$RESULT" | awk '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL)}' ## One line version. ~ same performance. # eval "${CMD} $@ 2>/dev/null" | awk -F "$SEP" -v filter="$pacman_size" -v pkg="$pacman_name" \ # '$0 ~ pkg {pkgname=$2} $0 ~ filter {gsub(/\..*/,"") ; printf("%6s KiB %s\n", $2, pkgname)}' | sort -u -k3 \ # | tee >(awk '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL)}') _pacman_unset_vars } fi ## Print deps list. if [ -f "/usr/bin/pacman" ]; then pacman-deps() { printhelp() { echo "Synopsis:" echo -e " $1 [-a|-h|-q] PACKAGES" echo -e " Arguments MUST be set before package list." echo echo "Usage:" echo -e " default:\tDisplay package dependencies. Output contains no double and is alphabetically sorted. It will only work for repos packages by default." echo -e " -a:\t\tUses Yaourt queries instead of repos database. It slows down query but allow displaying size of local any packages not available in repos." echo -e " -h:\t\tShow this help." echo -e " -q:\t\tUses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos." } CMD="pacman -Si" SEP=": " while getopts ":ahq" opt; do case $opt in a) CMD="yaourt -Si" ;; h) printhelp "$0" return 1 ;; q) CMD="pacman -Qi" ;; ?) printhelp "$0" return 1 ;; :) echo "Missing argument." echo "Use $0 -h for help." return 1 ;; esac done shift $(($OPTIND - 1)) if [ $# -eq 0 ]; then echo "Missing argument." echo "Use $0 -h for help." return 1 fi _pacman_set_vars eval "${CMD} $@ 2>/dev/null" | awk -F "$SEP" -v filter="$pacman_deps" '$0 ~ filter {gsub(/[>=<][^ ]*/,"",$2) ; gsub(/ +/,"\n",$2) ; print $2}' | sort -u _pacman_unset_vars } fi fi