
Ich habe das Pech, mit Dateinamen zu arbeiten, die Leerzeichen enthalten. Ich möchte Dateien verketten, deren Dateinamen Leerzeichen enthalten. Außerdem möchte ich die Dateinamen numerisch sortieren. Offensichtlich schlägt Folgendes fehl:
cat $(ls *.sql | sort -n)
da foo bar.sql
als zwei Argumente an übergeben werden cat
. Was ist hier die übliche Vorgehensweise?
Antwort1
Hier ist das nicht nötig ls
. Es ist die Shell, die den Verzeichnisinhalt auflistet, indem sie den *.sql
Glob erweitert.
Auf einem GNU- oder FreeBSD-System:
printf '%s\0' *.sql | sort -nz | xargs -r0 cat --
(Die Verwendung \0
anstelle von \n
zusammen mit -z/-0
stellt sicher, dass es auch mit Dateinamen funktioniert, die Zeilenumbruchzeichen enthalten.)
Beachten Sie, dass bei der numerischen Sortierung -n
davon ausgegangen wird, dass die Nummer am Anfang des Dateinamens steht.
Oder wenn Sie zsh
:
cat ./*.sql(.n)
(Der n
Glob-Qualifizierer dient zum Aktivieren der numerischen Sortierung (funktioniert auch, wenn die Zahl nicht am Anfang steht, vorausgesetzt, alle Dateinamen haben dasselbe Präfix (wie file12.sql
, file2.sql
). Ich habe .
auch hinzugefügt, dass nur normale Dateien eingeschlossen werden. Fügen Sie ihn hinzu, D
wenn Sie auch versteckte Dateien wie möchten .foo.sql
).
Antwort2
Sie können dies tun cat $(ls -1)
, wenn Sie IFS außer Kraft setzen. IFS ist die Shell-Variable, die BASH mitteilt, welche Zeichen als Trennzeichen verwendet werden sollen. Der Standardwert für IFS ist Leerzeichen, Tabulator, Zeilenumbruch. Wenn Sie IFS nur in Zeilenumbruch ändern, können Sie Folgendes tun cat $(ls -1)
.
An den anderen Antworten ist nichts auszusetzen, aber dies ist möglicherweise eine direktere Antwort auf die Frage, wie mit Leerzeichen im Allgemeinen umzugehen ist. Außerdem führt diese Antwort die IFS-Variable ein, mit der die meisten nicht vertraut sind.
#!/bin/bash
dir=$(mktemp -d)
for x in $(seq 10); do
echo $x > "$dir/$(date) $x.txt"
done
pushd $dir
ls -1 $dir
# Set IFS to newline only inorder to deal with the spaces in the file names
#
oldIFS=$IFS
IFS=$'\n'
cat $(ls -1 $dir)
IFS=$oldIFS
Ausgabe
[sri@localhost test]$ ./test
/tmp/tmp.IuXCBzbTLj ~/test
Mon Nov 17 06:38:52 EST 2014 10.txt
Mon Nov 17 06:38:52 EST 2014 1.txt
Mon Nov 17 06:38:52 EST 2014 2.txt
Mon Nov 17 06:38:52 EST 2014 3.txt
Mon Nov 17 06:38:52 EST 2014 4.txt
Mon Nov 17 06:38:52 EST 2014 5.txt
Mon Nov 17 06:38:52 EST 2014 6.txt
Mon Nov 17 06:38:52 EST 2014 7.txt
Mon Nov 17 06:38:52 EST 2014 8.txt
Mon Nov 17 06:38:52 EST 2014 9.txt
10
1
2
3
4
5
6
7
8
9
Hier ist ein Link zu Dokumentationen zu IFS. http://bash.cyberciti.biz/guide/$WENNS. Ich glaube, ich habe vor langer Zeit davon erfahren, als ich O'Riellys BASH-Buch gelesen habe.
Antwort3
Verwenden Sie xargs
(unter der Annahme der GNU-Implementierung) ein benutzerdefiniertes Trennzeichen (unter der Annahme, dass die Dateinamen keine Zeilenumbrüche enthalten):
ls -1d -- *.sql | sort -n | xargs -d "\n" cat --