Скопированный каталог, кажется, становится больше в месте назначения

У меня есть следующий код как часть сценария оболочки:

while [ $(ps -ef | awk '{print $2}' | grep -F "$CPPID") ]; do
    sleep 10
    awk -v "usbsize=$(/bin/df | grep -F $DEVICEMOUNTPOINTQ | awk '{print $3}')" -v "isosize=$(/bin/df | grep -F $ISOMOUNTPOINTQ | awk '{print $3}')" 'BEGIN { printf "%.1f", 100 * usbsize / isosize }' && echo "% copied..."
done

Это контролирует cp выполнение следующей операции:

cp -a "$ISOMOUNTPOINT"/* "$DEVICEMOUNTPOINT"

И это хорошо работает по большей части, до

90.5% copied...
94.2% copied...
97.8% copied...
101.6% copied...
102.7% copied...

Почему это превышает 100% размера источника? Копия от смонтированного циклом ISO до отформатированного NTFS раздела на карте флэш-памяти с интерфейсом USB. Я предполагаю, что это - вероятно, вещь файловой системы?

Что является моим примером, отсутствующим для составления соответствия размеров, так, чтобы когда cp завершается это - скопированных 100%, не 103%?

Спасибо.


Ре: щедрость

Я буду присуждать щедрость первому человеку, который произведет решение, подобное вышеупомянутому коду, который соответствует следующим критериям:

  • Сценарий должен смочь обнаружить копирование в 1:1 отношение
  • Сценарий не должен отображать значение сверх скопированных 100%, однако...
  • Сценарий не должен просто ограничивать дисплей в 100%, скопированных, когда он превышает его.

Если бы размер данных действительно отличается от источника до места назначения по некоторым причинам, то я хотел бы сценарий, который замечает это и все еще отображает фактическое скопированное отношение.

2
задан 12.06.2015, 19:31

3 ответа

Здесь Ваш упрощенный код и сделал более читаемым:

while ps -p $CPPID > /dev/null
do
    sleep 10
    usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    isosize=$(/bin/df $ISOMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%.1f%% copied...\n", 100 * usbsize / isosize }'
done

Ваше последнее awk строка могла быть заменена этими двумя:

    percent=$(echo "$usbsize / $isosize * 100" | bc -l)
    printf "%.1f%% copied...\n" $percent

Затем Вы могли сделать это незадолго до этого printf оператор:

if (( $(echo "$percent > 100" | bc) == 1 ))
then
    break
fi

и добавьте wait $CPPID сразу после конца while цикл. Это прекратит печатать прогресс, после того как 100% достигнуты.

Посмотрите, что управление процессами расценивает надежность PIDs (они переработаны).

Проблема, которую Вы видите, происходит, вероятно, из-за использования "используемого" значения целевой файловой системы, а не различия в текущем значении от значения запуска.

Попытайтесь добавить строку как это перед while цикл:

startsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')

и измените строку в цикле к:

usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk -v "start=$startsize" 'NR == 2 {print $3 - start}')

Конечно, это могло бы все быть преодолимо, если бы Вы использовали rsync --progress вместо cp.

Править:

Кроме того, попробуйте это в while цикл как показано выше для наблюдения, каковы числа, используемые в вычислении. Это могло бы дать представление относительно того, что продолжается:

    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%d of %d, %.1f%% copied...\n", usbsize, isosize, 100 * usbsize / isosize }'
1
ответ дан 08.12.2019, 05:08

Мое первое через - то, что это в основном зависело бы от типа файлов в исходном каталоге. Я думал бы, что вероятный преступник является редкими файлами. Редкий файл является тем где где статистика st_size! = (статистика st_blksize * статистика st_blocks); то есть, полный размер файла больше, чем количество блоков данных, связанных с inode файла. Любые освобожденные блоки читаются как блок нулей системными вызовами. Таким образом, при использовании CP (1) на редком файле целевой файл будет содержать больше блоков (содержащий только нули), чем исходный файл. du (1) и df (1) команды смотрят на количество блоков, не размер файла (файлов). Базовые файлы часто создаются как редкие файлы, так как они, возможно, должны отобразить память. Этот тип файла полезен для создания образов дисков, например, создавая диск виртуального хоста, который имеет размер 15 ГБ. Было бы очень расточительно выделить все блоки во время создания; размер (st_size) мог составить 15 ГБ, но фактическое количество блоков могло запуститься в 0.

Это - всего один тип файла, который мог взорваться при копировании. Не зная, что Вы имеете в своей файловой системе, трудно сказать, что еще могло бы делать это.

4
ответ дан 08.12.2019, 05:08

Можно использовать rsync в локально-единственном режиме, где у и источника и места назначения нет a ':' на имя, так, чтобы это вело себя как улучшенная команда копии. С параметром прогресса это отображает что-то подобное этому (источник):

$ rsync -r -v --progress -e ssh root@remote-server:~/pictures /home/user/
receiving file list ...
366 files to consider
pictures/IMG_1142.jpg
 4400662 100%   32.21kB/s    0:02:13 (xfer#31, to-check=334/366)
pictures/IMG_1172.jpg
 2457600  71%   32.49kB/s    0:00:29

Поскольку это не дает общий процент, другое решение могло бы состоять в том, чтобы использовать этот сценарий (источник):

#!/bin/sh
cp_p()
{
strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
  | awk '{
    count += $NF
        if (count % 10 == 0) {
           percent = count / total_size * 100
           printf "%3d%% [", percent
           for (i=0;i<=percent;i++)
              printf "="
           printf ">"
           for (i=percent;i<100;i++)
              printf " "
           printf "]\r"
        }
     }
     END { print "" }' total_size=$(stat -c '%s' "${1}") count=0
}

В действии:

% cp_p /mnt/raid/pub/iso/debian/debian-2.2r4potato-i386-netinst.iso /dev/null
76% [===========================================>                    ]

Можно также взглянуть на файлы перемещения с индикатором выполнения, который детализирует, как добавить к CP и mv, который-g переключают для показа прогресса.

2
ответ дан 08.12.2019, 05:08

Теги

Похожие вопросы