iiuc >prefixed lines will make it through gmail plain text mode without getting wrapped, let's see if that's true.. ># unlike mv, rename will never inadvertently copy files, it errors out if not same filesystem. ># rename's weakness is it neither will backup nor warn before replacing pre-existing targets. ># ># rb like rename, but if targets exist back them up into <curfs>/~ with unique name ># mb like mv -vb, but use rb (which puts backups into <curfs>/~ with unique name) ># cb like cf, but if targets exist put backups into <curfs>/~ with unique name ># co like cP, but if targets exist put backups into <curfs>/~ with unique name ># -~ like rm, but actually toss args into <curfs>/~ with unique name ># b~ copy args into <curfs>/~ with unique name ># bn ln args into <curfs>/~ with unique name ># cf cp -v, preserve dates&modes, sparse, use cp backup facility if target exists ># cu like cf but ignore if not more recent ># cP like cf but if target exists retain the owner&inode and copy over/into it ># ># backups as implemented here are all tossed into one flat directory per filesystem with unique ># names derived from their original name plus a number injected just before the extension > >alias cu='cp -vbau --sparse=always ${reflink=$(cp --reflink=auto --version>/dev/null 2>&1&&echo --reflink=auto)}' >alias cf='cp -vba --sparse=always ${reflink=$(cp --reflink=auto --version>/dev/null 2>&1&&echo --reflink=auto)}' >alias cP='cp -vPR --sparse=always ${reflink=$(cp --reflink=auto --version>/dev/null 2>&1&&echo --reflink=auto)} --preserve=mode,timestamps' #preserve=link only works if all faces of the link are copied, else it UNlinks >alias bn=' bN \~' > b~(){ B \~ "$@";} > -~(){ _ \~ "$@";} > bN()(h= D="$1";shift;N~ "$@";for a do \~;ln -- "$a" "$b$h$n$e"||exit;done) > _()(h= D="$1";shift;N~ "$@";for a do \~;mb "$a" "$b$h$n$e"||exit;done) > B()(h= D="$1";shift;N~ "$@";for a do \~;{ cmps "$a" "$c"&& > l "$c"|| #if already backed up just ls > cu -- "$a" "$b$n$e";}||exit;done) ># \~ explode arg into components > ~(){ a=${a%%*(/)} #assignment from $1 drops \001 et al characters in older bashes, assign from $a instead > d=${a%/*};[ "$d" = "$a" ]&&d= > e=${a##*/} #basename > b=${e%.*};[ "$b" ]||b=$e #sans extension > e=${e#$b};pushd "${d:-/}">/dev/null||exit #extension, if cd fails exit from () parent > b=$(/bin/pwd)/$b;popd >/dev/null #actual location > fs=${D%/*} #fs may be specified via the dirname of the first arg to B or _ > if [ "$fs" = "$D" ];then c=$b;while read -r m m r;do #if fs not specified find longest match in /proc/mounts > r=${b#$m};[ ${#r} -lt ${#c} ]&&c=$r fs=${m%%*(/)};done</proc/mounts;fi > D=${D#$fs/} > b=${b#$fs/} > b=${b##*(/)} > b=$fs/$D/${b//\//^} #unique name prefix > c=$(ls -tc1Nad "$b$h"~+([0-9])"$e" 2>/dev/null|head -1) #most recent existing > md -pm1777 "$fs/$D";} ># N~ survey args and set n= highest backup number +1 > N~(){ N=();for a do \~;N=("${N[@]}" "$b$h"~+([0-9])"$e");done > n=\~$(($(ls -U1Nad "${N[@]}" 2>/dev/null|(echo -1;while read -r b;do b=${b##*[/^]} n=${b%.*};[[ $n ]]||n=$b;n=${n##*~} > [[ $n =~ ^[0-9]+$ ]]&&echo $n;done)|sort -nr|head -1)+1));} > ># bq enumerate a=(sources) b=(targets), error if last arg not a dir and not 2 args ># Bq filter B=(pre-existing-targets), preserve prior exit status >funct bq(){ [[ -d ${@:$#} ]]&&a=("${@:1:$#-1}") a=("${a[@]%%*(/)}") b=("${@:$#}/${a[@]##*/}")||{ [[ $# = 2 ]]&&a=("$1") b=("$2");};Bq;} #NB no switches >funct Bq(){ r=$? B=();for c in "${b[@]}";do [[ -e $c ]]&&B=("$@" "$c");done;return $r;} >funct co()(! bq "$@"||b~ "${B[@]}"&&cP "$@") >funct cb()(! bq "$@"||-~ "${B[@]}"&&cf "$@") >funct mb()( bq "$@"&&for((i=0;i<${#a[@]};i++))do rb "${a[i]}" "${b[i]}" "${a[i]}"||exit;done) >funct rb()(a=("${@:3}") b=("${a[@]/$1/$2}");Bq;bn "${B[@]}"&&if [[ $(type -p rename.ul) ]];then rename.ul -v "$@";else rename "$@"&&echo "(${@:3}) -> (${b[@]})";fi) > >function cmps(){ [ -e "$1" ];ir=$? #like cmp but.. > [ -e "$2" ];jr=$? > [ $ir = 0 -a $jr = 0 ]||{ [ $ir = $jr ]&&return 0||return 1;} #return true if both don't exist > [ -x /usr/bin/cmp ]&&{ cmp -s "$1" "$2" &&return 0||return 1;} #use cmp if present > cmpsloop <(cat<"$1") <"$2" &&return 0||return 1;} >function cmpsloop(){ while true;do read -r i <"$1";ir=$? #read discards leading whitespace with default IFS > read -r j ;jr=$?; [ "$i" = "$j" ] ||return 1 #return false if different > [ $ir = 0 -a $jr = 0 ]||{ [ $ir = $jr ]&&return 0||return 1;};done;}