Hier ist ein Skript, das genau das tut, wonach Sie gefragt haben.
Die Anforderungen
- Die übertragenen Dateien müssen weniger als eine Schwellengröße betragen.
- Die Dateien müssen im Vergleich zum rsync-Ziel geändert werden.
- Wenn nicht alle Dateien übertragen werden können, müssen nur die zuletzt geänderten Dateien ausgewählt werden.
Die Details
Es wird verwendet rsync --dry-run
, um eine Liste der Dateien zu erstellen, die übertragen werden sollen (dies sind die geänderten Dateien). Anschließend wird eine Kombination aus du
und verwendet ls
, um Dateigröße und Zeit zu ermitteln. Anschließend werden die Dateien nach mtime sortiert und anschließend durchlaufen, bis die Gesamtgröße einen Schwellenwert überschreitet. Schließlich wird rsync erneut aufgerufen, wobei nur die zuletzt geänderten Dateien und die Gesamtgröße unter dem Schwellenwert liegen.
Das Skript ist etwas hässlich, aber es funktioniert. Eine große Einschränkung besteht darin, dass es auf dem Computer ausgeführt werden muss, der das Verzeichnis rsync from enthält. Es kann geändert werden, um ssh zu verwenden, um ein entferntes Verzeichnis zu verwenden, aber diese Übergröße bleibt dem Leser überlassen.
Schließlich sind die rsync
Optionen fest im Skript codiert. Dies ist jedoch eine einfache Änderung, wenn Sie sie in der Befehlszeile angeben möchten. Die Berechnung der Größe erfolgt ebenfalls in Bytes. Dies kann in Kilo / Mega / Gigabyte geändert werden, indem der Anruf auf du geändert und der Schwellenwert um denselben Faktor verringert wird.
Verwendungszweck
./rsyncrecent.sh rsync-from-directory rsync-to-directory
Dabei rsync-from-directory
handelt es sich um ein lokales Verzeichnis und rsync-to-directory
um ein lokales oder entferntes Verzeichnis. Die Standardoptionen sind fest codiert als -avz
und der Standardschwellenwert ist fest codiert als 10GiB
.
Das Skript
#!/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