Forum: PC-Programmierung Echo Printf Formatierung


von Walter S. (Gast)


Lesenswert?

Ich habe auf einem Linux System Ext4 einen Ordner mit Dateinamen, die 
Leerzeichen enthalten. Ein kleines Shellskript, welches die Dateinamen 
einlesen und in einer Datei speichern sollte, funktioniert. Was schief 
läuft ist die Formatierung.

echo ich das Ergebnis in die Datei, wird jeder von einem Leerzeichen 
getrennte Namensbestandteil als $datei interpretiert und mit einem 
eigenen Newline versehen.

das
ist
dann
der
dateiname.txt
1
ausgabe=$(find / -name "*.txt"); for datei in $ausgabe; do filename=$(basename $datei) && echo $filename >> ./textfile.txt; done

Bei printf das gleiche in Grün, nur das dieses Mal überhaupt kein 
Newline mehr eingesetzt wird, was dann so aussieht

datei name1.txtdatei name2.txt
1
ausgabe=$(find / -name "*.txt"); for datei in $ausgabe; do filename=$(basename $datei) && printf $filename >> ./textfile.txt; done

Bei dem printf-Ansatz habe ich versucht mittels | sed s///g einfach ein 
Newline am jeweiligen Ende des Dateinamens einzusetzen. Die Substitutuon 
klappt bei anderen Zeichen, aber nicht beim Newline. Escaping 
funktioniert nicht oder ist falsch | sed -e s/.txt/.txt\\n/g (wenn ich 
es grad richtig in Erinnerung habe.)

auch ausprobiert
1
printf "%b\n" $filename
Nüschte, wieder Essig.

Gibt es überhaupt eine einfache Möglichkeit mit echo oder printf so 
etwas 👆 umzusetzen?

von Olaf (Gast)


Lesenswert?

> Ich habe auf einem Linux System Ext4 einen Ordner mit Dateinamen, die
> Leerzeichen enthalten.

Hier damit auf, es ist dumm.

Du kannst dir jetzt irgendwas einfallen lassen um deine Probleme zu 
umgehen, aber irgendwann wird es wieder ein neues Programm geben, eine 
neues Script, irgendwas das damit wieder auf die Fresse faellt und dein 
System auf links krempelt.

Olaf

von Nikolaus S. (Firma: Golden Delicious Computers) (hns)


Lesenswert?

Der Fehler passiert weder in printf noch in echo sondern hier:
1
for datei in $ausgabe

Da werden alle Leerzeichen und NewLine aus $ausgabe als Feldtrenner 
(IFS) interpretiert.

Besserer Ansatz:
1
find / -name "*.txt" | while read dateiname; do filename="$(basename "$dateiname")" && echo "$filename" >> ./textfile.txt; done

Beachte die "" bei $basename und $filename. Speziell die beim echo 
"$filename" sind ebenfalls wichtig, falls der Dateiname gleich zwei 
Leerzeichen hintereinander haben sollte. Sonst gibt der echo nur eines 
aus.

: Bearbeitet durch User
von Walter S. (Gast)


Lesenswert?

Danke Nikolaus 🙏🙏🙏

Nicht nur für die Lösung, sondern auch für den Hinweis, was eigentlich 
das Problem war. Das mit den Feldtrenner war mir nicht klar. Damit kann 
ich arbeiten bzw. mir das nochmal genauer ansehen, was es damit auf sich 
hat. Nochmals Danke!

von Tom K. (ez81)


Lesenswert?

find -exec oder find -print0 mit xargs -0 sind etwas robuster und 
sollten sogar \n in Verzeichnis-/Dateinamen vertragen.

von Heiner (Gast)


Lesenswert?

Nikolaus S. schrieb:
> Da werden alle Leerzeichen und NewLine aus $ausgabe als Feldtrenner
> (IFS) interpretiert.

Das kann man ändern. Die Zeichen, die als Feldtrenner erkannt werden, 
stehen in der Variable IFS, also könnte man z.B. mit
1
IFS=; for datei in ...

... die Feldtrenner insgesamt deaktivieren. Man möchte das nicht unnötig 
global tun, ich halte es insgesamt nicht für die beste Lösung, aber der 
Vollständigkeit halber ...

von Rolf M. (rmagnus)


Lesenswert?

Tom K. schrieb:
> find -exec oder find -print0 mit xargs -0

Wollte ich auch grad schreiben. Ungefähr so:
1
find / -name '*.txt' -print0 | xargs -0 basename -a > textfile.txt

Alternativ mit einem eigenen basename-Aufruf für jede Datei statt einem 
für alle zusammen (der eine sehr lange Kommaozeile für basename ergeben 
könnte):
1
find / -name '*.txt' -exec basename {} \; > textfile.txt

Ach ja: Das *.txt sollte man wie hier gezeigt in '' setzen statt in "", 
denn sonst kommt ein ggf. unerwartetes Ergebnis raus, wenn im aktuellen 
Verzeichnis zur Zeit des Aufrufs eine Datei steht, deren Name auf .txt 
endet.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

Btw, der printf von find kann "%f": "File's name with any leading 
directories removed (only the last element)."
1
find / -name "*.txt" -printf "%f\n" >textfile.txt

Der Sinn des Ganzen erschließt sich mir allerdings nicht - eine Liste 
aller .txt-Dateien ohne Pfad?!?

Btw, ein "find /" ohne Beschränkung wie z.B. "-xdev" ist eh ziemlich 
fragwürdig ...

von Walter S. (Gast)


Lesenswert?

1
find ... -exec ... {} \; >

wäre auch gegangen, bzw. ging, aber ich wollte verstehen, was bei dieser 
👆Vorgehensweise das Problem war. Auch oder gerade weil es ein sehr 
grundsätzliches Verständnisproblem der Basics zu sein schien.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.