Как определить конец файла с помощью dd?

302
hebbo

Я создал тестовый файл 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=$ seek=$ skip=$ status=none retval=$? if [[ $retval -ne 0 ]]; then break fi count=$((count + 1)) done 

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

0
Отредактируйте его исходный код и перекомпилируйте. Ignacio Vazquez-Abrams 5 лет назад 0
Вам нужно удалить `status = none` и проверить` stderr` для строки `0 + N records in`, где` N` - количество байтов в частичном чтении в конце файла. AFH 5 лет назад 1
@AFH Точная строка зависит от локали. В таких случаях я временно [переопределяю настройки локализации] (https://unix.stackexchange.com/a/87763/108618): `LC_ALL = C dd…` Kamil Maciorowski 5 лет назад 0
Кстати, эффект `bs = ...` уже заключается в том, что он копирует файл кусками, поэтому, если все, чего вы хотите - скопировать файл кусками, вам не нужен дополнительный сценарий. (Вопрос не говорит нам * почему * вы хотите это сделать, поэтому это может быть [XY-проблема] (https://meta.stackexchange.com/questions/66377/what-is-the-xy- проблема)). dirkt 5 лет назад 2
Примечание: `[[` не работает в `sh` (хотя работает в` bash`), ваш скрипт не работает как есть. Используйте `[` с `sh`. Kamil Maciorowski 5 лет назад 1

1 ответ на вопрос

3
Kamil Maciorowski

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

#!/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-s для чтения и записи.
  2. teeразветвляется вывод чтения dd. Один экземпляр отправляется на запись dd.
  3. К тем же данным попадает wc -c, этот инструмент сообщает количество полученных байтов.
  4. Цикл завершается, если это число не соответствует размеру нашего блока.

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

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