Aqui está um script que faz exatamente o que você pediu.
Os requisitos
- Os arquivos transferidos devem totalizar menos que um tamanho de limite.
- Os arquivos devem ser modificados em comparação com o destino do rsync.
- Se nem todos os arquivos puderem ser transferidos, somente os arquivos modificados mais recentemente deverão ser selecionados.
Os detalhes
Ele usa rsync --dry-run
para criar uma lista de arquivos que seriam transferidos (esses são os arquivos modificados). Em seguida, ele usa uma combinação de du
e ls
para obter tamanhos de arquivo e mtime. Em seguida, ele classifica os arquivos por mtime e, em seguida, faz um loop sobre eles até que o tamanho total exceda um limite. Finalmente, ele chama novamente o rsync apenas com os arquivos que foram modificados recentemente e o tamanho total abaixo do limite.
O script é um pouco feio, mas funciona. Uma grande limitação é que ele deve ser executado na máquina que contém o diretório rsync from. Ele pode ser modificado para usar o ssh para usar um diretório remoto, mas esse excerso é deixado para o leitor.
Por fim, as opções rsync
são codificadas no script, mas essa é uma alteração fácil se você quiser especificá-las na linha de comando. Além disso, a matemática para calcular o tamanho é feita em bytes. Isso pode ser alterado para kilo / mega / gigabytes, modificando a chamada para du e reduzindo o limite pelo mesmo fator.
Uso
./rsyncrecent.sh rsync-from-directory rsync-to-directory
em que rsync-from-directory
é um diretório local e rsync-to-directory
é qualquer diretório local ou remoto. As opções padrão são codificadas como -avz
e o limite padrão é codificado como 10GiB
.
O script
#!/bin/bash
RSYNC=rsync
RSYNC_OPTS=-avz
THRESHOLD=10737418240
usage () {
echo >&2 "Usage: $0 from-location to-location"
exit 1
}
[ "$#" -eq 2 ] || usage
RSYNC_FROM=$1
RSYNC_TO=$2
echo "Fetching file list for $RSYNC $RSYNC_OPTS $RSYNC_FROM $RSYNC_TO"
# get list of changed files
FILES='$RSYNC $RSYNC_OPTS --dry-run $RSYNC_FROM $RSYNC_TO | sed -n '/list$/,/^$/{/sending.*list$/ d ; /^$/ d ; /\/$/ d ;; p}''
# reported files are relative to ..RSYNC_FROM, so rather than transforming filenames, lets just move there
pushd $RSYNC_FROM > /dev/null
# get modified time and sizes for all files
i=0
for FILE in $FILES
do
#strip first part of path so files are relative to RSYNC_FROM
FILE=${FILE#*/}
#FSIZE='ls -l $FILE | cut -f5 -d' ''
FSIZE='du -bs $FILE'
FMTIME='ls -l --time-style=+%s $FILE | cut -f6 -d' ''
FLIST[$i]='echo $FMTIME $FILE $FSIZE'
((i=$i+1))
done
# go back to original directory
popd > /dev/null
# sort list according to modified time
IFS=$'\n' FLIST=($(sort -rg <<<"${FLIST[*]}"))
max=$i
i=0
size=0
#NEWFLIST=''
# add up the files in mtime order until threshold is reached
for ((i=0; i<$max; i++))
do
s='echo ${FLIST[$i]} | cut -f3 -d' ''
f='echo ${FLIST[$i]} | cut -f2 -d' ''
((size=$size+$s))
if (( "$size" > "$THRESHOLD" ))
then
break
fi
NEWFLIST="$NEWFLIST $f"
echo $f >> /tmp/rsyncfilelist
done
$RSYNC $RSYNC_OPTS --dry-run $RSYNC_FROM --files-from=/tmp/rsyncfilelist $RSYNC_TO
rm /tmp/rsyncfilelist