Wie sortiert man Dateinamen mit Leerzeichen und verkettet die Dateien?

Wie sortiert man Dateinamen mit Leerzeichen und verkettet die Dateien?

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.sqlals 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 *.sqlGlob erweitert.

Auf einem GNU- oder FreeBSD-System:

printf '%s\0' *.sql | sort -nz | xargs -r0 cat --

(Die Verwendung \0anstelle von \nzusammen mit -z/-0stellt sicher, dass es auch mit Dateinamen funktioniert, die Zeilenumbruchzeichen enthalten.)

Beachten Sie, dass bei der numerischen Sortierung -ndavon ausgegangen wird, dass die Nummer am Anfang des Dateinamens steht.

Oder wenn Sie zsh:

cat ./*.sql(.n)

(Der nGlob-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, Dwenn 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 --

verwandte Informationen