Was ist falsch an meiner Verwendung von "find -print0"? [geschlossen]

7

Ich bin verwirrt von diesem Experiment (in Bash):

$ mkdir 'foo\n'
$ find . -print0 | od -c
0000000   .  \0   .   /   f   o   o   \   n  \0
0000012

Wie Sie sehen können, begrenzt "find" die Ausgabe korrekt mit Nullzeichen, aber es wird die neue Zeile im Verzeichnisnamen als "foo \ n" mit einem Backslash "n" umgangen. Warum macht es das? Ich sagte es "-print0", das besagt "Dies ermöglicht, dass Dateinamen, die Zeilenumbrüche enthalten ... von Programmen, die die Suchausgabe verarbeiten, korrekt interpretiert werden." Das Escapezeichen sollte nicht erforderlich sein, da "\ 0" das Trennzeichen ist, nicht "\ n".

Metamorph
quelle
14
Sie haben ein Verzeichnis mit dem wörtlichen foo\nNamen "Backslash" erstellt.
Michael Homer
7
Soo ... peinlich ... aber ich habe etwas aus den Antworten gelernt, danke euch allen.
Metamorphic
Wenn du eine gemacht lshättest, hättest du das gesehen.
Bakuriu
@ Bakuriu, nein, weil lsgenau das druckt, was ich an mkdir übergeben habe, 'foo\n'...
Metamorphic
Es gibt keine Neulinge in Ihrem Dateinamen, ‚\ n 'ist eine wörtliche 2-
Zeichen-

Antworten:

20

Das Problem liegt nicht darin find, sondern darin, wie Sie dieses Verzeichnis erstellen. Die Zeichenfolge in einfachen Anführungszeichen 'foo\n'ist eine Zeichenfolge mit 5 Zeichen, von denen die letzten beiden ein Backslash und ein Kleinbuchstaben "n" sind.

Doppelte Anführungszeichen helfen auch nicht, da Zeichenfolgen in doppelten Anführungszeichen in der Shell Backslash als Escape-Zeichen verwenden, aber keine der Backslash-Sequenzen im C-Stil wirklich interpretieren.

In einer Shell wie bash oder zsh usw. (aber nicht von Debian / Ubuntu) können Sie Folgendes verwenden $'...', das diese Sequenzen interpretiert:

$ mkdir $'foo\n'

(Weitere Informationen zu dieser Funktion finden Sie in der Bash- Dokumentation mit dem Namen "ANSI C Quoting".)

Eine weitere Option, die in jeder mit der Bourne-Shell kompatiblen Shell funktionieren sollte, ist das Einfügen eines tatsächlichen Zeilenumbruchs:

$ mkdir 'foo
'

Dies ist eine tatsächliche Zahl Returnam Ende der ersten Zeile, wobei nur das einfache Anführungszeichen in der zweiten Zeile geschlossen wird.

filbranden
quelle
6

Lassen Sie uns ein Verzeichnis mit dem Namen fooplus einer neuen Zeile erstellen:

$ mkdir $'foo\n'

Verwenden wir nun find:

$ find .  -print0 | od -c
0000000   .  \0   .   /   f   o   o  \n  \0
0000011

\n wird nicht entkommen.

Das Problem ist, dass mkdir 'foo\n'der Name so interpretiert wird, dass foogefolgt von \gefolgt von n. Wir können dies überprüfen mit:

$ printf '%s' 'foo\n' | od -c
0000000   f   o   o   \   n
0000005
John1024
quelle
1
Ich freue mich, den Verifikationsteil zu zeigen!
Pabouk