Это похоже xinput
вывод отклонений в файл, но не отклоняет вывод к терминалу. Достигнуть этого, вероятно xinput
используйте системный вызов
int isatty(int fd)
проверять, относится ли filedescriptor, который будет открыт, к терминалу или нет.
Я наткнулся на то же явление только что с названной программой dpic
. После того, как я изучил источник и некоторую отладку, я удалил строки, связанные с isatty
и все работало как ожидалось снова.
Но я соглашаюсь с Вами, что этот опыт является очень тревожащим ;)
Вот сценарий, который делает, что Вы попросили.
Это использует rsync --dry-run
создавать список файлов, которые были бы переданы (это измененные файлы). Это затем использует комбинацию du
и ls
получить размеры файла и mtime. Это затем сортирует файлы по mtime и затем циклам по ним, пока общий размер не превышает порог. Наконец, это называет rsync снова только с файлами, которые являются последний раз измененным и общим размером под порогом.
Сценарий немного ужасен, но он работает. Одно большое ограничение - то, что это должно быть выполнено на машине, содержащей rsync от каталога. Это может быть изменено для использования ssh для использования удаленного от каталога, но что excersize оставляют читателю.
Наконец, rsync
опции трудно кодируются в сценарий, но это - легкое изменение, если Вы хотите указать их на командной строке. Кроме того, математика для вычисления размера сделана в байтах. Это может быть изменено на килограмм/мега/гигабайты путем изменения вызова к du и сокращения порога тем же фактором.
./rsyncrecent.sh rsync-from-directory rsync-to-directory
где rsync-from-directory
локальный каталог и rsync-to-directory
любой локальный или удаленный каталог. Опции по умолчанию являются hardcoded как -avz
и порог по умолчанию является hardcoded как 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
Я использовал бы rsync "-пробный прогон" (или "-n") для получения списка более новых файлов. Затем я использовал бы другой rsync с опцией "-файлами - от =-" для отправки файлов. Промежуточный существует "ужасный" жемчуг.
Что-то вроде этого:
#!/usr/bin/perl
$source="/somedir";
$target="host:/remotedir";
$maxsize=10*1024**3; # 10GB
open (RSOUT,"|rsync -av --files-from=- $source $target");
open (RSIN, "rsync -avn $source $target |");
while (<RSIN>)
{
chomp;
last if (/^$/);
if (-f "$_")
{
next if ($size + -s "$_" > $maxsize);
$size += -s "$_";
printf RSOUT "%s\n", $_;
}
}
Обратите внимание, что я не протестировал больше чем с 10 ГБ, возможно, жемчуг переполнится в некотором пределе; для решения этого, вместо того, чтобы считать байты используют Кбайты:
$maxsize=10*1024**2; # 10M of Kbytes
...
$size +=( -s "$_")/1024;
Править: Я отметил, что это первое решение не отсортирует файл по mtime, вот больше полного решения (подобный сценарию удара, который был отправлен другим человеком).
#!/usr/bin/perl
use File::stat;
$source="/somedir/";
$target="host:/remotedir";
$maxsize=10 * 1024**3; # 10GB
open (RSOUT,"|rsync -av --files-from=- $source $target");
open (RSIN, "rsync -avn $source $target |");
while (<RSIN>)
{
chomp;
last if (/^$/);
if (-f "$_")
{
my $fileattr;
my $stat=stat($_);
$fileattr->{name}=$_;
$fileattr->{size}=$stat->size;
$hash{sprintf ("%s %s\n", $stat->mtime, $_)}=$fileattr;
}
}
foreach $key (reverse sort keys %hash)
{
next if ( ($size + $hash{$key}->{size}) > $maxsize);
$size += $hash{$key}->{size};
print RSOUT $hash{$key}->{name}, "\n";
}
Можно проанализировать отсортированный вывод du
. Утилиты Assuming GNU:
du -0ak | sort -z -k1n | awk -v 'RS=\0' -v 'ORS=\0' '
(size += $1) > 10*1024*1024 {quit}
{print substr($0, index(s, "\t")+1)}
' | xargs -0 cp -t destination
POSIXly, предполагая, что никакое имя файла не содержит символ новой строки:
du -ak | sort -k1n | awk '
(size += $1) > 10*1024*1024 {quit}
{print substr($0, index(s, "\t")+1)}
' | while IFS= read -r filename; do cp -- "$filename" /path/to/destination
Отметьте это du
подкаталоги пересечений. Чтобы избежать что, сказать du
на какие файлы Вы хотите воздействовать. В более общем плане можно использовать find
отфильтровать файлы.
find . -type f ! -name excluded-file -exec du -ak {} + |
sort -k1n | awk '
(size += $1) > 10*1024*1024 {quit}
{print substr($0, index(s, "\t")+1)}
' | while IFS= read -r filename; do cp -- "$filename" /path/to/destination
if (( "$size" > "$THRESHOLD" ))
условное выражение добавляет проверку (прежде чемbreak
) дляi==0
и если так,echo $f >> /tmp/rsyncfilelist
. – casey 06.12.2013, 01:04