Wie überprüfe ich, ob file1 ein Präfix von file2 ist?


13

Ich habe zwei Dateien mit den Größen 124665 und 124858 in Bytes und möchte überprüfen, ob file1 ein Präfix von file2 ist oder nicht.

Antworten:


11

Angenommen, Sie haben die Größe von file1in der Variablen FILE1_SZund Ihre headImplementierung unterstützt die (nicht standardmäßige) -cOption:

if head -c "$FILE1_SZ" file2 | cmp -s - file1; then
    echo "file1 is a prefix of file2"
else
    echo "file1 is not a prefix of file2"
fi

@ StéphaneChazelas Kannst du bitte erklären, warum cmpdas besser wäre als diffhier?
Joseph R.

7
Denn cmpführt einen einfachen Byte-zu-Byte-Vergleich durch und gibt zurück, sobald ein Unterschied festgestellt wird, während diffein Textdienstprogramm einen komplexen Algorithmus verwendet, um alle Unterschiede zwischen den beiden Dateien anzuzeigen, die Sie nicht interessieren.
Stéphane Chazelas

12

Wenn Ihr System den cmpBefehl von GNU hat diffutils, ist eine Option

cmp -n 124665 file1 file2

höchstens die ersten 124665 Bytes der beiden Dateien zu vergleichen und zu melden, ob sie sich unterscheiden - oder allgemeiner

cmp -n "$(wc -c < file1)" file1 file2

@StephaneChazelas Ich vermute mich selbst hier, aber wäre es besser gewesen, $(stat -c %s file1)die Größe in Bytes vorzuschlagen ? Wird wcdie gesamte Datei tatsächlich geöffnet und verarbeitet, um die Byteanzahl zu ermitteln?
Steeldriver

2
Nein, die meisten wcImplementierungen optimieren diesen Fall und führen a fstat()(oder / und a lseek(SEEK_END)) aus, um so effizient wie möglich zu sein. Andererseits stat -cist das GNU-spezifisch.
Stéphane Chazelas

1
Auch wenn Sie GNU-spezifisch benötigen cmp, können Sie davon ausgehen, dass GNU-spezifisch ist stat.
Barmar

3

GNU cmpkann das Problem auf einfachere Weise lösen:

cmp file1 file2

Es gibt vier mögliche Ausgänge (außer bei Fehlern).

  • Keine Ausgabe: Die Dateien sind identisch.

  • cmp: EOF on file1: file1 ist ein Präfix von file2.

  • cmp: EOF on file2: file2 ist ein Präfix von file1.

  • file1 file2 differ: byte NNN, line MMM: Keiner ist ein Präfix des anderen.

Leider ist die Verwendung in einem Skript etwas umständlich, da diese Fälle im Exit-Code nicht zu unterscheiden scheinen. Darüber hinaus EOF on file1gehen die Nachrichten an stderr, während die file1 file2 differNachricht an stdout geht.

Ich vermute, dass andere Versionen cmpetwas ähnliches tun, aber ich habe nicht überprüft.


1
cmpist kein reiner GNU-Befehl und stammt auch nicht von dort. Es war bereits in der ersten Unix-Version in den frühen 70ern. Die -nOption ist jedoch GNU-spezifisch.
Stéphane Chazelas

Sie könnten tuncmp file1 file2 2>&1 | grep EOF on file1
David Z

@ StéphaneChazelas: Das stimmt. Ich wollte damit nicht andeuten, dass dies cmpnur für GNU gilt, sondern nur, dass GNU cmpdie einzige Version ist, die ich ausprobiert habe. Ich habe einen Satz hinzugefügt, um dies zu verdeutlichen.
Nate Eldredge

@DavidZ: Ja, du könntest, aber es wird ein bisschen weniger robust. Stellen Sie sich vor, Sie versuchen dies mit zwei vom Benutzer bereitgestellten Dateien, von denen eine benannt file1und die andere benannt ist file12. (Oder schlimmer noch, was ist, wenn die zweite Datei benannt ist EOF on file1?) Solches robustes Verwenden cmpist wahrscheinlich viel schwieriger als das Schreiben des offensichtlichen 5-Zeilen-Programms in C ...
Nate Eldredge

Es kann jedoch Kontexte geben, in denen ein C-Programm nicht praktikabel ist. Und es ist nicht so schwer, es ziemlich robust zu machen, weil die Ausgabe von cmpso stark eingeschränkt ist. Wenn Sie die -xOption grepzum Anpassen der gesamten Zeile aktivieren, werden alle bis auf die exotischsten Fälle (z. B. Zeilenumbrüche im Dateinamen) berücksichtigt.
David Z
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.