Использование xxd
:
n=64
file=data
tmp=tmp
len=$(wc -c < "$file")
offset=$((len - n))
len=$((offset - n))
xxd -s -$n "$file" | xxd -r -s -$offset > "$tmp"
xxd -s $n -l $len "$file" | xxd -r >> "$tmp"
xxd -l $n "$file" | xxd -r >> "$tmp"
mv "$tmp" "$file"
Edit:
Другой подход заключается в использовании xxd
и sed
:
n=64; hd=$((n * 2))
file=data
tmp=tmp
xxd -c $n -p "$file" |
sed "1{x;d};:a;N;s/\n//;\${s/\(.*\)\(.\{$hd\}\)\$/\2\1/;G};ba" |
xxd -r -p > "$tmp"
mv "$tmp" "$file"
Вместо шести вызовов xxd
, это два к xxd
и один к sed
(и меньше операций чтения и записи файлов).
Объяснение команды sed
:
1{x;d}
- Сохранить первую строку шестнадцатеричных цифр в поле для удержания. Длина строки задается числом байтов для замены, используя параметр -c
xxd
.
:a
- Метка "а"
N
- Добавить следующую строку.
s/\n//
- Удалить встроенный перевод строки
\${
- Если это последняя строка ввода:
s/\(.*\)\(.\{$hd\}\)\$/\2\1/
- поменять местами последние $hd
байтов
G
- Добавить первые $n
байтов из пробела в конец. Поскольку это последняя строка, сценарий заканчивается.
}
- конец, если
ba
- ответвление к метке "a".
Кроме того, sed
может выполнять некоторые манипуляции с данными.