3

После fsck'а диска ext4, который работал в QNAP nas без fsck около четырех лет, у меня теперь есть ряд файлов, которые кажутся, но имеют правильный размер (обычно 8-12mib), но каждый байт их содержимого имеет значение null/NUL/00 (т. е. 0 повторяется снова и снова при просмотре в шестнадцатеричном редакторе).

Я проверил это с помощью инструмента «hexedit», а также сэмплировал байты различной длины с помощью «od»

Вместо того, чтобы искать среди 10 000+ файлов изображений NEF и JPEG, есть ли способ, которым я мог бы автоматизировать поиск этих файлов и записать их в список - чтобы я мог восстановить их из резервной копии?

2 ответа2

2

Предполагая, что ваши файлы содержат ТОЛЬКО строку NULL (без новой строки, \n), вы можете использовать grep и find, чтобы найти эти файлы.

Команда find собирает все файлы размером не менее 1 байта (-size +1c) в текущем каталоге, а затем использует grep, чтобы проверить, содержат ли они только повторения символа NULL:

$ find . -type f -size +1c -exec grep -m 1 -ovP "[^\0]" {} \; 
Binary file ./empty_file with spaces.jpg matches
Binary file ./empty_file matches

Флаг -v grep заставляет его печатать несовпадающие строки. -m 1 означает "Стоп после первого совпадения", -o означает печать только той части строки, которая соответствует (избегает печати пустых строк из других файлов), а P использует регулярные выражения Perl. Узор [^\0] означает любой символ NULL Отменив это (-v) и добавив флаг -m 1 , grep сообщит о совпадении, только если файл не содержит ничего, кроме NULL .

Наконец, вы можете передать это через cut и sed чтобы напечатать имя соответствующего файла:

$ find . -type f -size +1c -exec grep -m 1 -ovP "[^\0]" {} \; | cut -d ' ' -f 3- | sed 's/ matches//'
./empty_file with spaces.jpg
./empty_file
0

Хотя приведенный выше ответ является гораздо более тщательным (и менее запутанным) при проверке файлов, собрал следующее. Есть несколько дополнительных команд, чтобы справиться со странным способом, которым NAS обрабатывает имена файлов, но он использует 'od', чтобы получить первые 32 байта файла (мое обоснование состояло в том, что если первые 32 байта равны нулю, то Остальные, скорее всего, тоже будут, особенно для изображений)

find "$(pwd)" -type f -exec sh -c 'file=$(echo "{}" | sed "s/([\(\)])/\\\1/g"); check=$(od -N32 -w32 -x "$file"); if echo $check | grep --quiet " 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000"; then echo "$file" $check; fi' \;

Я попытался сделать это на подмножестве папок, которые, как я подозреваю, повреждены, и я сохранил результаты в файл. После проверки каждого файла вручную я был очень счастлив, что это было надежно.

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