Как побитно инвертировать файл в linux shell

Мне понадобилось изготовить файлик довольно большого размера - 16Кбайт, заполненный одними нулями и одними единичками. Но не смоволами юникода 0 и 1, а битами.
Итак. Получить нолики просто:

dd if=/dev/zero of=./16384_zeroes count=16384 bs=1

Проверить, что там побитовые нолики можно так:

$ xxd -b 16384_zeroes
00000000: 00000000 00000000 00000000 00000000 00000000 00000000  ......
00000006: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000000c: 00000000 00000000 00000000 00000000 00000000 00000000  ......
00000012: 00000000 00000000 00000000 00000000 00000000 00000000  ......
...
00003ffc: 00000000 00000000 00000000 00000000                    ....

Инвертировать побитово файл можно с помощью утилиты tr примерно так:

LC_ALL=C tr '\0-\377' '\377\376\375\374\373\372\371\370\367\366\365\364\363\362\361\360\357\356\355\354\353\352\351\350\347\346\345\344\343\342\341\340\337\336\335\334\333\332\331\330\327\326\325\324\323\322\321\320\317\316\315\314\313\312\311\310\307\306\305\304\303\302\301\300\277\276\275\274\273\272\271\270\267\266\265\264\263\262\261\260\257\256\255\254\253\252\251\250\247\246\245\244\243\242\241\240\237\236\235\234\233\232\231\230\227\226\225\224\223\222\221\220\217\216\215\214\213\212\211\210\207\206\205\204\203\202\201\200\177\176\175\174\173\172\171\170\167\166\165\164\163\162\161\160\157\156\155\154\153\152\151\150\147\146\145\144\143\142\141\140\137\136\135\134\133\132\131\130\127\126\125\124\123\122\121\120\117\116\115\114\113\112\111\110\107\106\105\104\103\102\101\100\77\76\75\74\73\72\71\70\67\66\65\64\63\62\61\60\57\56\55\54\53\52\51\50\47\46\45\44\43\42\41\40\37\36\35\34\33\32\31\30\27\26\25\24\23\22\21\20\17\16\15\14\13\12\11\10\7\6\5\4\3\2\1\0' < 16384_zeroes > 16384_ones

Зачем мне такое надо

А дальше я буду заливать этот файлик на флешку. У меня есть подозрения, что флеха (карточка Micro SD HC Kingston 16Gb SDC4 ) портит данные. Вот мы это и проверим.
Итак, смотрим сколько байтов у нас на флехе:

fdisk -l /dev/sdc
Disk /dev/sdc: 14.42 GiB, 15472787456 bytes, 30220288 sectors

То есть нам надо сделать файлик длинной 15472787456 байт, посчитать его контрольную сумму, залить его на флеху, слить обратно и снова посчитать контрольную сумму. Если всё в порядке - сумма сойдется.
Создаем файлик нужной длины. Посчитаем сколько раз нужно залить файлик размером 16Kb, чтобы забить всю флеху:

$ echo $(( 15472787456 / 16384 ))
944384

Теперь делаем маленький скриптик:

count=0; while true; do cat ./16384_ones | dd of=./16G_ones.img bs=16384 count=1 seek=$count status=none; if [[ $count > 944384 ]]; then break; fi; (( count++ )); echo $count; done

Он создаст нам файлик, в котором будет ровно 944384 * 16384 байт, в которых все биты - единички!
Зальем его на флеху:

dd if=./16G_ones.img of=/dev/sdc bs=16384 count=944384

А дальше считаем флеху и проверим контрольные суммы:

sha1sum -b ./16G_ones.img
c068f9b373027daaabc6214d401da9341e5fa545 *./16G_ones.img

dd if=/dev/sdc of=./sdc_ones bs=16384 count=944384
sha1sum -b ./sdc_ones 
d2c42aa3c9b5be47e3fc5ef8aced8f9d867d3aea *./sdc_ones

rm -f ./sdc_ones
dd if=/dev/sdc of=./sdc_ones bs=16384 count=944384
sha1sum -b ./sdc_ones 
25bac255911597a5962598e5c817e208baa63c72 *./sdc_ones

rm -f ./sdc_ones
dd if=/dev/sdc of=./sdc_ones bs=16384 count=944384
sha1sum -b ./sdc_ones 
984396d75505063aaef7f23a40f337f7a70b5294 *./sdc_ones

В результате - видно, что каждый раз при считывании контрольная сумма оказывается разная!!
Вывод - карточка битая! При этом - в логах ядра никаких ошибок чтения!

Как обойтись без файлика

Инвертируем нолики в единички налету и льем на диск:

export LC_ALL=C && dd if=/dev/zero bs=16384 count=3897983 | tr '\0-\377' '\377\376\375\374\373\372\371\370\367\366\365\364\363\362\361\360\357\356\355\354\353\352\351\350\347\346\345\344\343\342\341\340\337\336\335\334\333\332\331\330\327\326\325\324\323\322\321\320\317\316\315\314\313\312\311\310\307\306\305\304\303\302\301\300\277\276\275\274\273\272\271\270\267\266\265\264\263\262\261\260\257\256\255\254\253\252\251\250\247\246\245\244\243\242\241\240\237\236\235\234\233\232\231\230\227\226\225\224\223\222\221\220\217\216\215\214\213\212\211\210\207\206\205\204\203\202\201\200\177\176\175\174\173\172\171\170\167\166\165\164\163\162\161\160\157\156\155\154\153\152\151\150\147\146\145\144\143\142\141\140\137\136\135\134\133\132\131\130\127\126\125\124\123\122\121\120\117\116\115\114\113\112\111\110\107\106\105\104\103\102\101\100\77\76\75\74\73\72\71\70\67\66\65\64\63\62\61\60\57\56\55\54\53\52\51\50\47\46\45\44\43\42\41\40\37\36\35\34\33\32\31\30\27\26\25\24\23\22\21\20\17\16\15\14\13\12\11\10\7\6\5\4\3\2\1\0' | dd of=/dev/sdc bs=16384

Посчитаем SHA1, который должен быть:

export LC_ALL=C && dd if=/dev/zero bs=16384 count=3897983 | tr '\0-\377' '\377\376\375\374\373\372\371\370\367\366\365\364\363\362\361\360\357\356\355\354\353\352\351\350\347\346\345\344\343\342\341\340\337\336\335\334\333\332\331\330\327\326\325\324\323\322\321\320\317\316\315\314\313\312\311\310\307\306\305\304\303\302\301\300\277\276\275\274\273\272\271\270\267\266\265\264\263\262\261\260\257\256\255\254\253\252\251\250\247\246\245\244\243\242\241\240\237\236\235\234\233\232\231\230\227\226\225\224\223\222\221\220\217\216\215\214\213\212\211\210\207\206\205\204\203\202\201\200\177\176\175\174\173\172\171\170\167\166\165\164\163\162\161\160\157\156\155\154\153\152\151\150\147\146\145\144\143\142\141\140\137\136\135\134\133\132\131\130\127\126\125\124\123\122\121\120\117\116\115\114\113\112\111\110\107\106\105\104\103\102\101\100\77\76\75\74\73\72\71\70\67\66\65\64\63\62\61\60\57\56\55\54\53\52\51\50\47\46\45\44\43\42\41\40\37\36\35\34\33\32\31\30\27\26\25\24\23\22\21\20\17\16\15\14\13\12\11\10\7\6\5\4\3\2\1\0' | sha1sum -b -
9cee0b471cd582196b1c9fddf780186e69c526be *-

А теперь посчитаем фактический SHA1:

dd if=/dev/sdc bs=16384 count=3897983 | sha1sum -b -
9cee0b471cd582196b1c9fddf780186e69c526be *-

На новой флехе всё совпадает.

Enter your comment. Wiki syntax is allowed:
H T J I L
 
  • linux_faq/bash_bits_operations.txt
  • Last modified: 2020/04/14 13:32
  • by admin