Как сбросить часть двоичного файла
У меня есть двоичный файл и я хочу извлечь его часть, начиная с строки know byte (т. е. FF D8 FF D0) и заканчивая известной строкой byte (AF FF D9)
в прошлом я использовал dd
чтобы вырезать часть двоичного файла из начала / конца, но эта команда, похоже, не поддерживает то, что я прошу.
какой инструмент на терминале можно это сделать?
6 ответов
в одной трубе:
xxd -c1 -p file |
awk -v b="ffd8ffd0" -v e="aaffd9" '
found == 1 {
print
str = str
if (str == e) {found = 0; exit}
if (length(str) == length(e)) str = substr(str, 3)}
found == 0 {
str = str
if (str == b) {found = 1; print str; str = ""}
if (length(str) == length(b)) str = substr(str, 3)}
END{ exit found }' |
xxd -r -p > new_file
test ${PIPESTATUS[1]} -eq 0 || rm new_file
идея в том, чтобы использовать awk
между xxd
для выбора необходимой части файла. После того, как 1-й шаблон найден,awk
выводит байт до 2-го паттерна и выход.
случай, когда 1-й шаблон найден, но 2-й не должен учитываться. Это делается в END
часть awk
скрипт, который возвращает ненулевой статус выхода. Это catch by bash
' s ${PIPESTATUS[1]}
где я решил удалить новый файл.
обратите внимание, что пустой файл en также означает, что ничего не найдено.
найдите начальную / конечную позицию, затем извлеките диапазон.
$ xxd -g0 input.bin | grep -im1 FFD8FFD0 | awk -F: '{print }'
0000cb0
$ ^FFD8FFD0^AFFFD9^
0009590
$ dd ibs=1 count=$((0x9590-0xcb0+1)) skip=$((0xcb0)) if=input.bin of=output.bin
это должно работать со стандартными инструментами (xxd, tr, grep, awk, dd). Это правильно обрабатывает проблему "разбиение шаблона по линии", также ищите шаблон, выровненный только по смещению байта (не грызть).
file=<yourfile>
outfile=<youroutputfile>
startpattern="ff d8 ff d0"
endpattern="af ff d9"
xxd -g0 -c1 -ps ${file} | tr '\n' ' ' > ${file}.hex
start=$((($(grep -bo "${startpattern}" ${file}.hex\
| head -1 | awk -F: '{print }')-1)/3))
len=$((($(grep -bo "${endpattern}" ${file}.hex\
| head -1 | awk -F: '{print }')-1)/3-${start}))
dd ibs=1 count=${len} skip=${start} if=${file} of=${outfile}
Примечание: скрипт выше использует временный файл, чтобы предотвратить двоичное > шестнадцатеричное преобразование дважды. Пространство/торговля-время передать результат xxd
прямо в два grep
. ОДН-вкладыш также возможен, за счет ясность.
можно использовать tee
и именованный канал, чтобы предотвратить хранение временного файла и преобразование вывода дважды, но я не уверен, что это будет быстрее (xxd быстро) и, безусловно, сложнее писать.
посмотреть этой ссылке для способа сделать двоичный grep. После того, как у вас есть начальное и конечное смещение, вы должны иметь возможность с dd
чтобы получить то, что вам нужно.
вариация на тему awk
решение, которое предполагает, что ваш двоичный файл, преобразованный в hex с пробелами, помещается в память:
xxd -c1 -p file |
tr "\n" " " |
sed -n -e 's/.*\(ff d8 ff d0.*aa ff d9\).*//p' |
xxd -r -p > new_file
другое решение в sed
, но используя меньше памяти:
xxd -c1 -p file |
sed -n -e '1{N;N;N}' -e '/ff\nd8\nff\nd0/{:begin;p;s/.*//;n;bbegin}' -e 'N;D' |
sed -n -e '1{N;N}' -e '/aa\nff\nd9/{p;Q1}' -e 'P;N;D' |
xxd -r -p > new_file
test ${PIPESTATUS[2]} -eq 1 || rm new_file
1-й sed
печать из ff d8 ff d0
до конца файла. Обратите внимание, что вам нужно столько N
на -e '1{N;N;N}'
как есть байты в вашем 1-м шаблоне меньше.
2-й sed
печать с начала файла до aa ff d9
. Еще раз обратите внимание, что вам нужно столько N
на -e '1{N;N}'
как есть байты в вашем 2-м шаблоне меньше один.
опять же, тест необходим, чтобы проверить, найден Ли 2-й шаблон, и удалить файл, если это не так.
отметим, что Q
команда является расширением GNU для sed
. Если у вас его нет, вам нужно выбросить остальную часть файла, как только шаблон будет найден (в цикле, таком как 1st sed
, но не печать файла), и проверьте после преобразования hex в binary, что new_file заканчивается шаблоном Райта.