Voici un script qui fait exactement ce que vous avez demandé.
Les exigences
- Les fichiers transférés doivent totaliser moins d'une taille seuil.
- Les fichiers doivent être modifiés par rapport à la destination rsync.
- Si tous les fichiers ne peuvent pas être transférés, seuls les fichiers modifiés les plus récents doivent être sélectionnés.
Les détails
Il utilise rsync --dry-run
pour construire une liste de fichiers qui seraient transférés (ce sont les fichiers modifiés). Il utilise ensuite une combinaison de du
et ls
pour obtenir les tailles de fichier et mtime. Il trie ensuite les fichiers par mtime, puis les boucle jusqu'à ce que la taille totale dépasse un seuil. Enfin, il appelle à nouveau rsync avec uniquement les fichiers dont la taille totale a été modifiée le plus récemment et sous le seuil.
Le script est un peu moche, mais ça marche. Une grande limitation est qu'il doit être exécuté sur la machine contenant le répertoire rsync. Il peut être modifié pour utiliser ssh pour utiliser un répertoire distant, mais cette excersize est laissée au lecteur.
Enfin, les rsync
options sont codées en dur dans le script, mais c'est un changement facile si vous souhaitez les spécifier sur la ligne de commande. De plus, les calculs pour calculer la taille se font en octets. Cela peut être changé en kilo / méga / gigaoctets en modifiant l'appel à du et en réduisant le seuil du même facteur.
Usage
./rsyncrecent.sh rsync-from-directory rsync-to-directory
où rsync-from-directory
est un répertoire local et rsync-to-directory
n'importe quel répertoire local ou distant. Les options par défaut sont codées en dur comme -avz
et le seuil par défaut est codé en dur comme 10GiB
.
Le scénario
#!/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