Вот скрипт, который делает именно то, что вы просили.
Требования
- Передаваемые файлы должны иметь размер меньше порогового.
- Файлы должны быть изменены по сравнению с назначением rsync.
- Если не все файлы могут быть переданы, должны быть выбраны только самые последние измененные файлы.
Детали
Он использует rsync --dry-run
для создания списка файлов, которые будут переданы (это измененные файлы). Затем он использует комбинацию du
и, ls
чтобы получить размеры файлов и mtime. Затем он сортирует файлы по mtime, а затем перебирает их, пока общий размер не превысит пороговое значение. Наконец, он снова вызывает rsync только с файлами, которые были недавно изменены и имеют общий размер ниже порогового значения.
Сценарий немного уродлив, но работает. Одно большое ограничение заключается в том, что он должен выполняться на машине, содержащей директорию rsync from. Его можно изменить, чтобы использовать ssh для использования удаленного директории from, но этот размер оставляется читателю.
Наконец, rsync
параметры жестко запрограммированы в скрипте, но это легко изменить, если вы хотите указать их в командной строке. Также математика для вычисления размера выполняется в байтах. Это можно изменить на килограмм / мега / гигабайт, изменив вызов du и уменьшив порог на тот же коэффициент.
Применение
./rsyncrecent.sh rsync-from-directory rsync-to-directory
где rsync-from-directory
это локальный каталог и rsync-to-directory
любой локальный или удаленный каталог. Параметры по умолчанию жестко заданы как, -avz
а пороговое значение по умолчанию жестко задано как 10GiB
.
Сценарий
#!/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