Вот скрипт, который делает именно то, что вы просили.
Требования
- Передаваемые файлы должны иметь размер меньше порогового.
- Файлы должны быть изменены по сравнению с назначением 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