Я создал тестовый файл 10 МБ:

dd if=/dev/zero of=file.txt count=1024 bs=10240

Затем я написал скрипт ниже, чтобы скопировать этот файл кусками. Но похоже, что dd не обнаруживает EOF и всегда возвращает 0, поэтому цикл while продолжается вечно.

#!/bin/sh

block_size=1048576
count=0
retval=0
while true
do
        dd if=./file.txt of=other.txt bs=${block_size} seek=${count} skip=${count} status=none
        retval=$?
        if [[ $retval -ne 0 ]]; then
                break
        fi
        count=$((count + 1))
done

Итак, как я могу заставить dd возвращать разностный код, когда он проходит EOF?

1 ответ1

3

Я не знаю, зачем тебе эта штуковина; может быть для целей обучения. Хорошо, вот более сложное устройство:

#!/bin/bash

block_size=1048576   # must be a plain number, without any suffix
count=0
while true
do
   retbytes=`dd if=./file.txt bs=$block_size skip=$count count=1 status=none |
             tee >(dd of=other.txt bs=$block_size seek=$count status=none) |
             wc -c`
   [ "$retbytes" -eq "$block_size" ] || break
   count=$((count + 1))
done

Ваш оригинальный скрипт использует sh и [[ . Это не работает В моей версии [ достаточно там, где мне это нужно (sh бы это понимало), но мне все равно нужен bash из-за синтаксиса >(…) другом месте.

Возможно, вы не заметили, но ваш скрипт обрабатывает весь file.txt при первом проходе, потому что вы не сказали dd остановиться после первого фрагмента. (Обратите внимание, что dd делает это порциями, т. Е. Единственный первый запущенный dd делает то, что должен делать весь ваш скрипт). Позже в цикле последовательные dd -s снова и снова перезаписывают (потому что пропускают все больше и больше); каждый раз до конца file.txt хотя. Они работают совершенно бесполезно (если входной файл не изменится за это время). Я думаю, что ваше намерение заключалось в том, что делает count=1

Вот как работает мой скрипт:

  1. Он использует отдельные dd ы для чтения и записи.
  2. tee раздваивает вывод чтения dd . Один экземпляр идет на написание dd .
  3. Те же данные попадают в wc -c , этот инструмент сообщает количество полученных байтов.
  4. Цикл завершается, если это число не соответствует размеру нашего блока.

Примечание. $block_size должен быть в формате, который позволяет сравнивать с выводом wc . Следовательно, это должно быть простое число без суффикса, несмотря на то, что dd может понять, чего достаточно в опции bs= .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .