mOCo schrieb:
Ja, das war auch meine Idee - allerdings habe ich keine Whitespaces am Ende, sondern die Datei hat einfach Windows-Zeilenenden. Nach Ändern auf Linux-Zeilenabschluss funktioniert das ganze wie gedacht.
Aha!
Was mich allerdings trotzdem irritiert - warum kann der echo-Befehl die Variable korrekt auswerten, der find-Befehl jedoch nicht? Der Inhalt der Variablen ist doch für beide gleich?
echo
gibt ja nur aus und hängt selbst ans Ende ein Newline an, wenn man nicht die Option -n verwendet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | $ echo test >| datei
$ od -t x1c datei
0000000 74 65 73 74 0a
t e s t \n
0000005
$ unix2dos datei
unix2dos: converting file datei to DOS format...
$ od -t x1c datei
0000000 74 65 73 74 0d 0a
t e s t \r \n
0000006
$ var=$(cat datei)
$ echo -n "$var" | od -t x1c
0000000 74 65 73 74 0d
t e s t \r
0000005
$ echo "$var" | od -t x1c
0000000 74 65 73 74 0d 0a
t e s t \r \n
0000006
$ echo -n "$var"
$ echo "$var"
test
$ echo -n "$var"
$ st
|
Wie Du am Ende sehen kannst, wenn Du das mal selbst ausprobierst, führt ein \r nur zu einem Carriage Return, d.h. der Cursor wandert an den Anfang der Zeile. Wenn dann ein Newline \n folgt, dann merkt man das gar nicht. Und genau das passiert, wenn Du echo
ohne -n verwendest.
| $ read var <datei
$ echo -n "$var" | od -t x1c
0000000 74 65 73 74 0d
t e s t \r
0000005
$ echo "$var" | od -t x1c
0000000 74 65 73 74 0d 0a
t e s t \r \n
0000006
$ echo "$var"
test
|
Mit anderen Worten, bei der Ausgabe via echo
sieht man den \r nicht, aber find -name
vergleicht natürlich den gesamten Dateinamen, da ein \ŗ ein gültiges Zeichen im Namen ist.
awk ist für mich bis jetzt ein Buch mit sieben Siegeln, wa macht dein Befehl genau?
Der Teil mit ARGIND==1 {idx[$0]=1}
wird nur für das erste Kommandozeilenargument ausgeführt - Deine Indexdatei. Es wird ein Hash namens "idx" derart gefüllt, dass jede Zeile (ohne folgenden Newline!) als Schlüssel mit Wert "1" eingetragen wird.
Der Teil ARGIND>1 {if (idx[$NF]) print}
wird für alle folgenden Dateien ausgeführt - in diesem Fall die Eingabe von Stdin. Das wiederum ist die Ausgabe von find
. Da ich mittels "-F /" einen Forward Slash als Feldtrenner nutze, landet in NF
die Anzahl der Pfadelemente und in $NF
der Wert des letzten Elementes, also des Dateinamens. ("find -type f" liefert nur die Namen von Dateien - nicht von Verzeichnissen und Pipes.) Jetzt wird nur noch geschaut, ob es einen Wert in "idx" mit dem Schlüssel des aktuellen Namens gibt und dann die gesamte Zeile (also der komplette Pfad) ausgegeben. Man kann die Bedingung auch noch vor die Klammer ziehen - dann wird es noch etwas kürzer, weil print
ausgeführt wird, wenn kein Block da ist:
| find / -type f | awk -F / 'ARGIND==1 {idx[$0]=1} ARGIND>1 && idx[$NF]' /tmp/Songlist.txt -
|
☺