509 lines
12 KiB
Bash
509 lines
12 KiB
Bash
## -*- mode:sh -*- #
|
|
################################################################################
|
|
## Shell -- Functions.
|
|
## Date 2013-03-03
|
|
################################################################################
|
|
|
|
## Functions that can be useful outside a shell (like in Emacs or Ranger) should
|
|
## be written in stand-alone script instead.
|
|
|
|
## Colored man pager.
|
|
man()
|
|
{
|
|
# mb = ?
|
|
# md = bold (titles, commands)
|
|
# so = status bar
|
|
# us = italic (arguments, files)
|
|
env \
|
|
LESS_TERMCAP_mb=$(printf "\e[1;31m") \
|
|
LESS_TERMCAP_md=$(printf "\e[0;36m") \
|
|
LESS_TERMCAP_me=$(printf "\e[0m") \
|
|
LESS_TERMCAP_se=$(printf "\e[0m") \
|
|
LESS_TERMCAP_so=$(printf "\e[1;4;37m") \
|
|
LESS_TERMCAP_ue=$(printf "\e[0m") \
|
|
LESS_TERMCAP_us=$(printf "\e[0;33m") \
|
|
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"
|
|
}
|
|
|
|
## Network operations
|
|
if [ -n "$(command -v 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
|
|
|
|
netspeed ()
|
|
{
|
|
local INTERFACE="eth0"
|
|
if [ -n "$1" ]; then
|
|
INTERFACE="$1"
|
|
fi
|
|
|
|
if [ ! -d "/sys/class/net/${INTERFACE}" ]; then
|
|
echo "Error: no such interface (${INTERFACE})"
|
|
return
|
|
fi
|
|
|
|
local RX_BEFORE=$(cat /sys/class/net/${INTERFACE}/statistics/rx_bytes)
|
|
local TX_BEFORE=$(cat /sys/class/net/${INTERFACE}/statistics/tx_bytes)
|
|
sleep 1
|
|
local RX_AFTER=$(cat /sys/class/net/${INTERFACE}/statistics/rx_bytes)
|
|
local TX_AFTER=$(cat /sys/class/net/${INTERFACE}/statistics/tx_bytes)
|
|
|
|
local RX_RESULT=$(((${RX_AFTER:-0}-${RX_BEFORE:-0})/1024))
|
|
local TX_RESULT=$(((${TX_AFTER:-0}-${TX_BEFORE:-0})/1024))
|
|
|
|
echo "RX $RX_RESULT KiB/s"
|
|
echo "TX $TX_RESULT KiB/s"
|
|
}
|
|
|
|
## CPU usage
|
|
##
|
|
## A typical CPU array is (on Linux Kernel 3.0)
|
|
## cpu 158150 0 52354 18562746 1472 0 10198 0 0 0
|
|
##
|
|
## The meanings of the columns are as follows, from left to right:
|
|
##
|
|
## user: normal processes executing in user mode
|
|
## nice: niced processes executing in user mode
|
|
## system: processes executing in kernel mode
|
|
## idle: twiddling thumbs
|
|
## iowait: waiting for I/O to complete
|
|
## irq: servicing interrupts
|
|
## softirq: servicing softirqs
|
|
## ... (see 'man 5 proc' for further details)
|
|
##
|
|
## Only the first 4 values are interesting here.
|
|
cpuusage()
|
|
{
|
|
local cpuarray
|
|
local f1
|
|
local f2
|
|
local f3
|
|
local f4
|
|
|
|
cpuarray="$(grep 'cpu ' /proc/stat)"
|
|
f1=$(echo $cpuarray | cut -f3 -d' ')
|
|
f2=$(echo $cpuarray | cut -f4 -d' ')
|
|
f3=$(echo $cpuarray | cut -f5 -d' ')
|
|
f4=$(echo $cpuarray | cut -f6 -d' ')
|
|
|
|
local totalA=$(($f1+$f2+$f3+$f4))
|
|
local idleA=$f4
|
|
|
|
sleep 0.4
|
|
|
|
cpuarray="$(grep 'cpu ' /proc/stat)"
|
|
f1=$(echo $cpuarray | cut -f3 -d' ')
|
|
f2=$(echo $cpuarray | cut -f4 -d' ')
|
|
f3=$(echo $cpuarray | cut -f5 -d' ')
|
|
f4=$(echo $cpuarray | cut -f6 -d' ')
|
|
|
|
local totalB=$(($f1+$f2+$f3+$f4))
|
|
local idleB=$f4
|
|
|
|
local totaldiff=$((${totalB:-0}-${totalA:-0}))
|
|
|
|
if [ $totaldiff -eq 0 ]; then
|
|
echo 0
|
|
else
|
|
echo "$((100 - 100 * ($idleB-$idleA) / $totaldiff ))"
|
|
fi
|
|
}
|
|
|
|
## Webcam
|
|
webcam ()
|
|
{
|
|
## With mplayer.
|
|
mplayer -fps 30 -tv driver=v4l2:width=640:height=480:device=/dev/video0 tv:// -flip
|
|
}
|
|
|
|
## Vim-only: search the vim reference manual for a keyword.
|
|
## Usage: :h <keyword>
|
|
if [ -n "$(command -v vim)" ]; then
|
|
:h()
|
|
{
|
|
vim --cmd ":silent help $@" --cmd "only";
|
|
}
|
|
fi
|
|
|
|
## 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
|
|
}
|
|
|
|
## Will not work for Bourne Shell.
|
|
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
|
|
}
|
|
|
|
if [ -n "$(command -v highlight)" ] ; then
|
|
hlt-viewer ()
|
|
{
|
|
_printhelp()
|
|
{
|
|
cat<<EOF
|
|
Usage: $1
|
|
|
|
Highlight themes viewer for 256-colors terminals.
|
|
|
|
highlight is a tool for listing printing. This script displays a preview for
|
|
every highlight's theme. Press ENTER to display next preview. Press anything
|
|
else then ENTER to quit.
|
|
EOF
|
|
}
|
|
|
|
if [ $# -gt 0 ]; then
|
|
_printhelp "$0"
|
|
return
|
|
fi
|
|
|
|
local SAMPLE="$(cat <<EOF
|
|
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 ) );
|
|
}
|
|
}
|
|
EOF
|
|
)"
|
|
|
|
unset DUMMY
|
|
for i in $(highlight -w | grep -v "\s\|^$"); do
|
|
echo "******************** $i ********************"
|
|
highlight -S c -O xterm256 <(echo "$SAMPLE") -s "$i"
|
|
read DUMMY
|
|
if [ -n "$DUMMY" ]; then
|
|
return
|
|
fi
|
|
done
|
|
}
|
|
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
|
|
}
|
|
|
|
## Extended info
|
|
typex()
|
|
{
|
|
if [ $# -ne 1 ] || [ -z "$(command -v "$1")" ]; then
|
|
echo "Provide an existing command as parameter."
|
|
return
|
|
fi
|
|
|
|
if [ -z "$(command -v "$1" | grep ^/)" ]; then
|
|
type "$1"
|
|
return
|
|
fi
|
|
|
|
local xpath="$(type $1 | cut -d' ' -f3)"
|
|
ls -l "$xpath"
|
|
file "$xpath" | cut -d':' -f2 | cut -b 2-
|
|
}
|
|
|
|
## BAD CODE. This function will try to find an input binary file in the content
|
|
## of binary files in current folder. It does not work on big file because
|
|
## 'find' and 'grep' have an argument length limit.
|
|
bindatasearch()
|
|
{
|
|
echo "Deprecated function."
|
|
return
|
|
|
|
if [ $# -ne 2 ] -; then
|
|
echo "Usage: $0 FILECHUNK BIGFILE"
|
|
return
|
|
fi
|
|
|
|
if [ $(du -b Cover.jpg | awk '{print $1}') -gt 1048576 ]; then
|
|
echo "[$1] file size must not exceed 1MB."
|
|
return
|
|
fi
|
|
|
|
## The awk command suppresses first column, spaces and line breaks.
|
|
local SOURCE
|
|
SOURCE=$(od -tx8 "$1" | awk '($1="")1 gsub ( /\s/,"") { printf ("%s", $0) }')
|
|
|
|
local FILEDUMP
|
|
FILEDUMP=$(od -tx8 "$1" | awk '($1="")1 gsub ( /\s/,"") { printf ("%s", $0) }')
|
|
|
|
# grep -q "$SOURCE" <(echo "$FILEDUMP")
|
|
|
|
## This special, not well-known syntax allows us to execute a set of
|
|
## functions upon 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 allows the use of
|
|
## arguments. Note it will not work
|
|
# find "$TARGET" -type f -exec sh -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 "Usage: $0 VIDEOPORT"
|
|
return
|
|
fi
|
|
|
|
xrandr --output "$1" --auto --right-of $(xrandr | sed -n "/current/{n;p;q}" | cut -f1 -d" ")
|
|
}
|
|
|
|
xmultioff ()
|
|
{
|
|
if [ $# -ne 1 ]; then
|
|
echo "Usage: $0 VIDEOPORT"
|
|
return
|
|
fi
|
|
|
|
xrandr --output "$1" --off
|
|
}
|
|
|
|
## Extended pgrep -a.
|
|
pgex ()
|
|
{
|
|
ps aux | grep "$(echo "$@" | sed 's/./[&]/;q')"
|
|
}
|
|
|
|
## Keymap view in terminal
|
|
echokeymap ()
|
|
{
|
|
if [ $# -ne 1 ]; then
|
|
1="$HOME/.xkb/symbols/usex"
|
|
fi
|
|
|
|
awk '/━|┃|│|─/ {gsub(/^\/\/ /, ""); print $0}' "$1"
|
|
}
|
|
|
|
## Dump optical disc to iso
|
|
clonecd ()
|
|
{
|
|
if [ $# -ne 1 ]; then
|
|
echo "Usage: $0 ISO (without extension)"
|
|
return
|
|
fi
|
|
|
|
## Slow
|
|
# readcd f="$1.iso" -v retries=32 timeout=30 -s speed=16 -noerror
|
|
|
|
## Fast?
|
|
readcd f="$1.iso" -v retries=5 timeout=30 -noerror
|
|
|
|
DRIVE=/dev/sr0
|
|
# dd if=$DRIVE of='$1.iso' bs=2048 count=$(isosize -d 2048 $DRIVE) conv=sync,notrunc
|
|
}
|
|
|
|
browse ()
|
|
{
|
|
# Compatible with ranger 1.4.2 through 1.6.*
|
|
#
|
|
# Automatically change the directory in bash after closing ranger.
|
|
#
|
|
# This is a shell wrapper script to automatically change the directory to the
|
|
# last visited one after ranger quits. To undo the effect of this function, you
|
|
# can type "cd -" to return to the original directory.
|
|
|
|
tempfile="$(mktemp)"
|
|
ranger --choosedir="$tempfile" "${@:-$(pwd)}"
|
|
if [ -f "$tempfile" ] && [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
|
|
cd -- "$(cat "$tempfile")"
|
|
fi
|
|
rm -f -- "$tempfile"
|
|
}
|
|
|
|
bb ()
|
|
{
|
|
for i; do
|
|
git clone git@bitbucket.org:/ambrevar/$i
|
|
done
|
|
}
|
|
|
|
##==============================================================================
|
|
## Pacman functions
|
|
##==============================================================================
|
|
|
|
if [ -n "$(command -v pacman)" ]; then
|
|
## Get detailed file list for the specified packages, omitting folders.
|
|
pql ()
|
|
{
|
|
pacman -Ql "$@" | grep -v "/$"
|
|
}
|
|
|
|
pli ()
|
|
{
|
|
expac -t %F-%T '%-8l %n' | sort -rn | head -${1:-30}
|
|
}
|
|
fi
|
|
|
|
##==============================================================================
|
|
## FreeBSD functions
|
|
##==============================================================================
|
|
|
|
if [ "$(uname)" = FreeBSD ]; then
|
|
## TODO: useless ?
|
|
# mqs()
|
|
# {
|
|
# local str="$(echo "$@" | sed -E 's/[ \t]+/\\|/g')"
|
|
# (cd /usr/ports && make quicksearch name="$str")
|
|
# }
|
|
|
|
port-list()
|
|
{
|
|
pkg_info | cut -f1 -d' '
|
|
}
|
|
|
|
port-size()
|
|
{
|
|
pkg_info -Qsb "$@" | sed 's/\([^:]*\):\(.*\)/\2 KiB \1/g'
|
|
}
|
|
|
|
mcd()
|
|
{
|
|
local DEST=$(pkg_search -r "$@" | head -n1 | awk '{print $2}')
|
|
cd "$DEST"
|
|
}
|
|
|
|
fi
|
|
|
|
##==============================================================================
|
|
## TeXlive functions
|
|
##==============================================================================
|
|
|
|
## TeXlive
|
|
if [ -d "/usr/local/texlive" ]; then
|
|
## WARNING: it is important to set umask properly, otherwise users might
|
|
## not have authorization to use the packages.
|
|
|
|
## This is bad pratice to write args without double quotes, but since we
|
|
## are sure there is no space in TeX Live packages, it is OK here.
|
|
|
|
tli ()
|
|
{
|
|
sudo sh -c 'umask 022 && tlmgr install $0 $@' "$@"
|
|
}
|
|
|
|
tlr ()
|
|
{
|
|
sudo sh -c 'umask 022 && tlmgr remove $0 $@' "$@"
|
|
}
|
|
fi
|
|
|