Es wurde versucht, Dateien zu finden, die nur NULs enthalten, aber einige andere

7

Die Dateien, die ich zu finden / aufzulisten versuche, sind:

  • Beliebige Größe (0 Bytes akzeptiert)
  • Besteht nur aus ASCII-NUL-Zeichen (0x00)
  • Wenn andere Zeichen als 0x00 vorhanden sind, sollte die Datei nicht aufgelistet werden.

Der Befehl, den ich jetzt habe, ist:

grep -RLP '[^\x00]' .

Was funktioniert, aber es findet auch eine Datei, die nur aus zwei Bytes besteht: 0xFF, 0xFE. Ich weiß nicht warum.

Gibt es einen besseren Befehl, um solche Dateien zu finden?

pbies
quelle
Beachten Sie, dass die Standardsystemcodierung für Ubuntu UTF-8 und nicht ASCII ist. Obwohl bis zu Byte 0x7F, sind sie identisch.
Wjandrea

Antworten:

9

Kurz gesagt, hier wird grepversucht, Ihre Datei als Unicode-Daten zu interpretieren. Die Sequenz 0xFF, 0xFE ist ein Byte Order Marker für UTF-16 .

(In meinen Tests stimmen selbst andere Sequenzen mit zwei 0xFFs oder zwei 0xFEs usw. immer noch nicht mit dem regulären Ausdruck überein '[^\x00]', da diese selbst bei dem Versuch, UTF-8 auszuführen, als Nichtzeichen betrachtet werden.)

Die Verwendung eines Gebietsschemas, in dem Unicode nicht für Zeichentypen verwendet wird, sollte dies beheben. Dies können Sie durch Festlegen der Umgebungsvariablen LC_CTYPE erreichen . Verwenden Sie das CGebietsschema, um die ASCII-Codierung zu erzwingen (daher kein Unicode aktiviert):

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

UPDATE : Wie von @steeldriver hervorgehoben, handelt grep immer noch zeilenweise, sodass Dateien mit NUL-Bytes und Zeilenumbrüchen weiterhin übereinstimmen.

Die Lösung von @ DavidFoerster mit grep's -zlöst dieses Problem gut, indem die NUL-Bytes als Trennzeichen verwendet werden.

Alternativ habe ich ein kurzes Python 3-Skript ( allzeroes.py) entwickelt, um zu überprüfen, ob der Inhalt der Datei alle Nullen sind:

#!/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)

Mit denen Sie findalle Übereinstimmungen rekursiv suchen können:

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

Ich hoffe das hilft.

filbranden
quelle
3
+1 Obwohl grepdies zeilenbasiert ist, werden auch Dateien ausgegeben, die vollständig aus Zeilenumbrüchen bestehen. Möglicherweise können Sie dies umgehen, indem Sie den nullterminierten Modus mit angeben -z(obwohl dadurch alle regulären Textdateien vollständig in den Speicher verwischt werden). Auch ich denke nicht, dass -Phier erforderlich ist?
Steeldriver
1
Ich bin nicht glücklich, finddass das Python-Skript für jede Datei ausgeführt wird. Dies sollte alles in Python-Skript gemacht werden. Schließlich sogar Perl.
pbies
@pbies True, aber auf der anderen Seite kann dieses Skript in verschiedenen Szenarien verwendet werden. Es wird nur eines versucht, auf gute alte Unix-Art und Weise. Auf diese Weise ist es möglich, es auf eine Weise zusammenzustellen, die nicht möglich wäre, wenn es nur durch Durchlaufen eines Verzeichnisbaums verwendet werden könnte.
Filbranden
@filbranden wir haben hier ein Szenario und eine Frage. Die Antwort sollte zur Frage passen.
pbies
2

Sie können grepden alternativen nullterminierten Zeilenmodus missbrauchen und somit nach Dateien suchen, die nur leere Zeilen enthalten:

grep -L -z -e . ...

Ersetzen Sie ihn ...durch den Dateisatz, den Sie scannen möchten (hier :) -R ..

Erläuterung

  • -z, --null-data- Behandeln Sie die Eingabe als eine Reihe von Zeilen, die jeweils durch ein Null-Byte (das ASCII-NUL-Zeichen) anstelle einer neuen Zeile abgeschlossen werden. 1
  • -e .- .Als Suchmuster verwenden, dh mit einem beliebigen Zeichen übereinstimmen.
  • -L, --files-without-match- Normale Ausgabe unterdrücken; Drucken Sie stattdessen den Namen jeder Eingabedatei, aus der normalerweise keine Ausgabe gedruckt worden wäre. Der Scanvorgang wird beim ersten Spiel beendet. 1

Testfall

Installieren:

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

Lauftest:

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

1 Von der grep(1)Handbuchseite .

David Foerster
quelle
0

Ich werde eine andere Antwort geben, nämlich das Skript, das ich verwende. Aus einem bestimmten Ordner ausgeführt, werden alle NUL-Dateien wiederholt und aufgelistet:

shopt -s globstar
for file in ./**
do
    [ -d "$file" ] || LC_CTYPE=C grep -qP '[^\x00]' "$file" || echo "$file"
done
pbies
quelle