Попытка найти файлы, которые содержат только NULs, но получение некоторых других

Файлы, которые я пытаюсь найти/перечислить:

  • Любой размер (принятых 0 байтов)
  • Состойте только из символов ASCII NUL (0x00)
  • Если существуют какие-либо символы кроме 0x00, файл не должен быть перечислен.

Команда, которую я имею теперь:

grep -RLP '[^\x00]' .

Который работает, но это также находит файл, который состоит только из двух байтов: 0xFF, 0xFE. Не знайте почему.

Там какая-либо лучшая команда должна найти такие файлы?

7
задан 16 August 2018 в 18:32

4 ответа

Короче говоря, что происходит, вот это grep попытка состоит в том, чтобы интерпретировать Ваш файл как данные Unicode. Последовательность 0xFF, 0xFE является Маркером Порядка байтов для UTF-16.

(В моем тестировании даже другие последовательности, включающие два 0xFF или два 0xFE и т.д., все еще не соответствовали бы '[^\x00]' regex, с тех пор пытаясь сделать UTF-8 их считали бы несимволами.)

Используя локаль, которая не использует Unicode для типов символов, должен зафиксировать это, которое можно выполнить путем установки переменной среды LC_CTYPE. Используйте C локаль для принуждения кодирования ASCII (таким образом, никакой Unicode не включил):

LC_CTYPE=C grep -RLP '[^\x00]' .

ОБНОВЛЕНИЕ: Как указано @steeldriver, grep все еще действует на линию за линией основание, таким образом, файлы, содержащие байты NUL и новые строки, будут все еще соответствовать.

Решение @DavidFoerster с помощью grep's -z делает хорошее задание решения этой проблемы, с помощью байтов NUL, поскольку разделители добиваются цели.

С другой стороны, я придумал короткий сценарий Python 3 (allzeroes.py) чтобы проверить, является ли содержание файла, все обнуляет:

#!/usr/bin/python3
import sys
assert len(sys.argv) == 2
with open(sys.argv[1], 'rb') as f:
    for block in iter(lambda: f.read(4096), b''):
        if any(block):
            sys.exit(1)

Который можно использовать в a find определять местоположение всех соответствий рекурсивно:

$ find . -type f -exec allzeroes.py {} \; -print

Я надеюсь, что это помогает.

9
ответ дан 23 November 2019 в 06:23

Я предоставлю другой ответ, который я использую. Запущенный из определенной папки вернется и выведет список всех файлов NUL:

shopt -s globstar
for file in ./**
do
    [ -d "$file" ] || LC_CTYPE=C grep -qP '[^\x00]' "$file" || echo "$file"
done
0
ответ дан 23 November 2019 в 06:23

Можно злоупотребить grepальтернативный режим пустой нагруженной линии и таким образом ищет файлы, которые содержат только пустые строки:

grep -L -z -e . ...

Замена ... с набором файла, который Вы хотите просканировать (здесь: -R .).

Объяснение

  • -z, --null-data – Рассматривайте вход как ряд строк, каждый завершенный нулевым байтом (символ ASCII NUL) вместо новой строки 1
  • -e . – Использовать . как шаблон поиска, т.е. соответствие любой символ.
  • -L, --files-without-match – Подавите нормальный вывод; вместо этого распечатайте название каждого входного файла, из которого обычно не печатался бы никакой вывод. Сканирование остановится на первом соответствии 1

Тест

Установка:

: > empty
truncate -s 100 zero
printf '%s\0' foo bar > foobar

Запущенный тест:

$ grep -L -z -e . empty zero foobar
empty
zero

1 От grep(1) страница руководства.

2
ответ дан 23 November 2019 в 06:23

Вы можете использовать этот код PHP для поиска всех файлов с содержимым NULL.

<?php
$pattern = '';
$directory = new RecursiveDirectoryIterator("./");
$iterator = new RecursiveIteratorIterator($directory);
if ($pattern) {
    $regex = new RegexIterator($iterator, $pattern);
} else {
    $regex = $iterator;
}
foreach($regex as $file) {
    if (is_dir($file)) continue;
    $contens = file_get_contents($file);
    $contens = trim($contens);
    if (strlen($contens) == 0) {
        echo "$file\n";
    }
}
-1
ответ дан 3 November 2020 в 01:06

Другие вопросы по тегам:

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