Aquí hay un script que hace justo lo que pediste.
Los requisitos
- Los archivos transferidos deben sumar menos de un umbral.
- Los archivos deben modificarse en comparación con el destino rsync.
- Si no se pueden transferir todos los archivos, solo se deben seleccionar los archivos modificados más recientemente.
Los detalles
Se utiliza rsync --dry-run
para crear una lista de archivos que se transferirán (estos son los archivos modificados). Luego usa una combinación de du
y ls
para obtener tamaños de archivo y mtime. Luego ordena los archivos por mtime y luego los repite hasta que el tamaño total excede un umbral. Finalmente, vuelve a llamar a rsync con solo los archivos modificados más recientemente y con el tamaño total por debajo del umbral.
El guión es un poco feo, pero funciona. Una gran limitación es que debe ejecutarse en la máquina que contiene el directorio rsync. Se puede modificar para usar ssh para usar un directorio remoto desde, pero ese exceso se deja al lector.
Finalmente, las rsync
opciones están codificadas en el script, pero este es un cambio fácil si desea especificarlas en la línea de comandos. Además, la matemática para calcular el tamaño se realiza en bytes. Esto se puede cambiar a kilo / mega / gigabytes modificando la llamada a du y reduciendo el umbral en el mismo factor.
Uso
./rsyncrecent.sh rsync-from-directory rsync-to-directory
donde rsync-from-directory
es un directorio local y rsync-to-directory
es cualquier directorio local o remoto. Las opciones predeterminadas están codificadas como -avz
y el umbral predeterminado está codificado como 10GiB
.
La secuencia de comandos
#!/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