Wie wähle ich ein Feld / eine Spalte aus der Ausgabe von "ls -l" aus?

22

Mein Ziel ist täuschend einfach (zumindest für mich). Ich möchte die Ausgabe von ls -loder übernehmen ls -lhund nur ein Feld auswählen.

Ich möchte, dass dies so kugelsicher wie möglich ist. Ich gehe also davon aus, dass Dateinamen eine variable Anzahl von Leerzeichen haben können, nicht alle Felder die gleiche Länge haben usw.

Bonuspunkte für ein Skript, das den Namen des Feldes (oder auch nur eine Feldnummer) verwendet und dann den Inhalt des Feldes zurückgibt.

Ich möchte mich umdrehen

Bildbeschreibung hier eingeben

in:

Bildbeschreibung hier eingeben

soandos
quelle

Antworten:

41

Versuchen Sie es ls -l | awk '{print $7}'.

awk Wählt Spalten aus, damit sie für diese Aufgabe perfekt sind.

Corey Whitaker
quelle
3
Wie von @ormaaj erklärt: Verlassen Sie sich nicht darauf, dass Informationen an bestimmten Orten mit verfügbar sind ls. Der findBefehl ist enorm hilfreich.
Paddy Landau
@PaddyLandau Wie verwende ich den Befehl find, um eine Dateigröße in Megabyte zu drucken, wie ich sie kann ls -l --block-size=M?
SurpriseDog
@Benjamin - Der lsBefehl ist kein POSIX-Standard, daher kann ein Skript, das von abhängt ls, auf verschiedenen Systemen oder sogar im Laufe der Zeit fehlerhaft sein . Weitere Informationen finden Sie in der Antwort von @ormaaj auf dieser Seite. Eine Möglichkeit, das zu tun, was Sie verlangen, ist eine Bash-Schleife. Hier ist ein Beispiel. for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done. Natürlich echowürden Sie stattdessen Ihre Verarbeitung verwenden.
Paddy Landau
@PaddyLandau Ich habe gerade die Ausgabe des Befehls find weitergeleitet, auf ... | xargs -d '\n' du -mdie es genauso gut funktioniert.
SurpriseDog
@ Benjamin Vielleicht möchten Sie sich die -execOption ansehen find.
Paddy Landau
17

Niemals ls analysieren . Verwenden Sie GNU find. Oder wenn Portabilität ist nicht wichtig, stat(1).

find . -maxdepth 1 -printf '%Td\n'

Informationen zum zeilenweisen Lesen anderer Daten als Listen von Dateinamen und zum Aufteilen in Felder finden Sie unter: BashFAQ / 001

Es gibt keine Methoden zum zuverlässigen Lesen einer durch Zeilenumbrüche getrennten Liste von Dateinamen, die unter den meisten Umständen sinnvoll sind.

ormaaj
quelle
1

Sie können die bestimmte Spalte in der Shell wie folgt abrufen:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

oder awkwie in @Corey Antwort gezeigt , cut -c44-45würde auch nach der Anpassung funktionieren (da lshat Spalten behoben), oder was auch immer sonst, das Hauptproblem ist jedoch, dass es nicht zuverlässig und kugelsicher ist (z. B. unter Unix kann es sein $6, nicht $7, und es Änderungen in Abhängigkeit von Argumenten) machen es nicht maschinenfreundlich, daher wird es nicht empfohlen, den lsBefehl überhaupt zu analysieren .

Verwenden Sie am besten verschiedene verfügbare Befehle wie findoder stat, um die Ausgabe nach Bedarf zu formatieren. Beispielsweise:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

Führen Sie das folgende Beispiel aus, um eine Spalte mit nur Tagen an Änderungen zurückzugeben:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

Es ist zu beachten, dass GNU statandere Optionen als BSD haben kann stat, so dass es unter verschiedenen Betriebssystemen immer noch nicht kugelsicher ist.

Kenorb
quelle
1
+1 für die Erwähnung, dass ls nicht analysiert werden sollte sowie für die Verwendung von stat. dateist jedoch falsch eingerichtet. Sie sollten hinzufügen --date=$ymd, da dateder aktuelle Tag von sich aus gedruckt wird, aber der Zweck hier ist es, das Datumsformat der Datei zu konvertieren
Sergiy Kolodyazhnyy
Der ls -la | cut -c32-33Befehl ist absolut unzuverlässig, nicht nur wegen der möglichen Fallstricke bei den Dateinamen, sondern einfach, weil er von der Länge der Benutzernamen und der Größe der Dateien abhängt. Der stat -c "%x" *.*Befehl sieht in *.*Ordnung aus, aber wenn Sie ihn verwenden, beschränken Sie ihn nur auf Dateinamen, die einen Punkt enthalten. Ich denke, die Absicht war es, auch versteckte Dateien zu fangen; in diesem Fall sollten Sie Globbing für dotfiles ermöglichen vorher und verwenden *statt *.*: shopt -s dotglob; stat -c "%x" * | [...].
Kos
Ah und was Serg auch gesagt hat, sollten Sie --date="$ymd"dem dateBefehl hinzufügen , sonst wird der aktuelle Tag des Monats gedruckt.
Kos
Danke für die Kommentare. Ich habe die Probleme angesprochen und ein besseres erstes Beispiel geliefert.
Kenorb