Wie man Dateien ohne Verzeichnis auflistet und nach Namen filtert (ls options)

42

Ich habe ein Verzeichnis namens uploads. Es enthält eine Reihe von Dateien sowie einige Unterverzeichnisse, die wiederum Dateien enthalten.

Gibt es eine Möglichkeit, wie ich (in einem Schritt) Folgendes tun kann:

  1. NUR die Dateien im Stammverzeichnis für Uploads auflisten - Ich möchte die Namen der Unterordner oder deren Inhalt nicht sehen.

    und

  2. Listen Sie KEINE Dateien auf, die mit beginnen t_

Ich weiß über die -dFlagge Bescheid , aber sie bringt mir nicht das, was ich will.

EmmyS
quelle

Antworten:

53

Das klingt nach einem Job für find.

  • Verwenden Sie -maxdepthdiese Option, um nur das aktuelle Verzeichnis zurückzugeben und nicht rekursiv in Unterordnern zu suchen
  • Verwenden Sie -type fdiese Option, um nur Dateien und keine Verzeichnisse oder Geräteknoten oder was auch immer zurückzugeben
  • Verwenden Sie eine Kombination, wenn -notund -nameum die Dateien mit Namen zu vermeiden, die Sie nicht möchten

Es könnte so zusammenkommen:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Caleb
quelle
Vielen Dank! Ich bin ziemlich neu in CLI und hatte noch nie zuvor einen Fund verwendet. Ich werde es auf jeden Fall weiter untersuchen.
EmmyS
2
@EmmyS: Vielleicht findest du hier noch einen kleinen Trick, der nützlich ist. @ Gilles erwähnte -exec ls -lG -- {} +in seiner Antwort die Verwendung von ls, um die Ausgabe mit zusätzlichen Optionen zu erhalten. Sie können -lsdiesem Fund auch nur einen hinzufügen , um eine schnelle und unsaubere Annäherung an die Detailansicht von ls zu erhalten.
Caleb
18

GNU ls (dh der Befehl ls auf nicht eingebetteten Linux-Systemen und Cygwin, der auch auf einigen anderen Unices verfügbar ist) bietet die Option, einige Dateien anhand ihres Namens auszublenden. Es gibt jedoch keine Möglichkeit, Verzeichnisse zu ignorieren.

ls --hide='t_*' uploads

Ein anderer Ansatz ist, Ihre Shell das Matching durchführen zu lassen. Bash, ksh und zsh haben ein Negationsmuster, !(t_*)das mit allen Dateien außer den übereinstimmenden übereinstimmt t*. in bash muss diese funktion mit shopt -s extglobund in zsh mit aktiviert werden setopt ksh_glob. Zsh hat auch die äquivalente Syntax, mit ^t_*der aktiviert werden muss setopt extended_glob. Dies ignoriert Verzeichnisse immer noch nicht. Zsh verfügt über eine zusätzliche Funktion, mit der Dateien nicht nur nach Namen, sondern auch nach Metadaten und mehr abgeglichen werden können: Glob-Qualifikatoren . Fügen Sie (.)am Ende eines Spiels zu regulären Dateien zu beschränken. Die Negation ^ist Teil der Namensübereinstimmungssyntax und ^t_*(.)bedeutet daher "Alle regulären Dateien stimmen nicht überein t_*" und nicht "Alle Dateien, die nicht mit regulären Dateien übereinstimmen t_*".

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Wenn Sie ohne fortgeschrittene Werkzeuge auskommen, können Sie dies auf jedem Unix mit tun find. Es ist nicht die Art von Dingen, die Sie normalerweise in der Befehlszeile eingeben würden, aber es ist leistungsstark und präzise. Caleb hat bereits gezeigt, wie man das mit GNU find macht . Die -maxdepthOption ist nicht portabel. Sie können -prunestattdessen verwenden, um die findRekursion portabel zu stoppen .

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Ersetzen Sie -printdurch -exec ls -lG -- {} +, um lsdie gewünschten Optionen für die Dateien auszuführen .

Alle obigen Befehle verbergen Punktdateien (dh Dateien, deren Name mit a beginnt .). Wenn Sie wollen , dass sie angezeigt werden , übergeben Sie -Azu ls, oder fügen Sie Dglob - Qualifikationsspiel in zsh ( ls uploads/^t_*(.D)). Mit findkönnen Sie einen anderen Ansatz verwenden, um die Rekursion nur auf einer Ebene durchzuführen (Punktdateien werden findnicht speziell behandelt). Dies funktioniert nur dann vollständig, wenn Sie findim aktuellen Verzeichnis ausgeführt werden.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Gilles 'SO - hör auf böse zu sein'
quelle
3
Hast du einen Tagjob? ;-) Ich bin immer wieder erstaunt, wie ausführlich und detailliert Ihre Antworten sind, selbst bei den einfachsten Fragen hier bei Unix SE! :)
alex
Vielen Dank! Großartiges Detail. Ich weiß nicht, ob ich "fortgeschrittene Werkzeuge" habe oder nicht. Ich bin auf einem Mac bei der Arbeit (obwohl Linux zu Hause ist, also bin ich sicher, dass dies irgendwann nützlich sein wird.)
EmmyS
@EmmyS: Für deine Linux-Box sollte meine Verwendung -maxdepthfunktionieren, aber das "Portabilitäts" -Problem, auf das Gilles sich bezieht, ist, dass das BSD find(das ich auch unter OSX finde) ein etwas anderes Tier ist, also brauchst du vielleicht auch seine Antwort. @ Gilles: +1 für den zsh-Trick!
Caleb
1
@Gilles: Einige nicht so saftige Kommentare zu prunes kommen mir in den Sinn, aber ich lasse es los, indem ich sage, wenn ich auf meinen eigenen Systemen herumspiele, wie oft der Gedanke " würde dieser Befehl funktionieren, wenn ich eingeschaltet wäre AIX, Solaris oder MINIX3 "ist ungefähr ... Standby ... Es fällt mir schwer, einen Zählerstand zu erhalten ... das Display ist eingefroren 0.00.
Caleb
2
Hat Gnu lskeine --use-telepathyOption? Auf diese Weise können Sie am schnellsten nur die gewünschten Dateien anzeigen. Es ist jedoch möglicherweise nicht portabel.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
quelle
Was steht $9in dieser Aussage?
Emmys
3
@EmmyS Bedeutet das 9. Feld / die 9. Spalte der Ausgabe. Diese Antwort versucht, die Ausgabe zu analysierenls .
JW013
print $ NF` wäre besser, IMO. $ NF bedeutet die Anzahl der Felder, die 9 betragen würde, und wird in AWK häufig verwendet, um andere über $ NF zu unterrichten.
Elijah Lynn
1
ls -l | grep -v ^d | grep name$
RICARDO MARMOLEJO GARCIA
quelle
Was würde diese Lösung (die mehrere Befehle und Pipes erfordert) vorziehen find?
HalosGhost
Es ist übersichtlich, leicht zu lesen und entspricht der ls-Befehlskonvention. Ich finde es leichter, mich zu erinnern, als die Argumente des Befehls find. Jedem sein und ein dickes Lob für Optionen!
Tkjef
0

Lassen Sie es mich mit lsund Pipes ausprobieren:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

Sagen wir, die letzte Spalte ist die 9..

Y0NG
quelle
1
Was ist, wenn Dateien mit Leerzeichen vorhanden sind?
Jordanien
0

Wenn das Portabilitätsproblem von find -maxdepth ein Problem darstellt, können Sie Folgendes verwenden:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Ich bin kein Experte, aber ich denke, das sollte funktionieren. Ich nehme an, es sieht ein bisschen kryptisch aus, aber wenn Sie awk sprechen, ist es wirklich nicht. $ NF könnte anstelle von $ 9 verwendet werden. Sie könnten auch tun:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

was dasselbe macht (aber vielleicht weniger effizient als das erstere ???).

Eigentlich sieht es nach dem Nachdenken über die anderen Beiträge so aus

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

ist ein noch kürzerer und klarerer Weg.

Bitte korrigiert mich jemand, wenn ich falsch liege. :-)

kkaszub
quelle
Das Parsen lsist im Allgemeinen keine gute Idee . Ihre awk-Tricks schlagen beispielsweise mit Dateinamen mit Leerzeichen fehl.
Mat
@mat - Danke für die Korrektur. Nach dem Lesen des Artikels , dass Sie (und jw013) wiesen darauf hin, sehe ich , dass ls nicht ausgeben richtige Dateinamen vertraut werden kann. Selbst wenn ich den awk - Code neu zu schreiben , war alles von $ 9 bis zum Ende der Zeile (einschließlich Leerzeichen) zu drucken, diese ls Ausgabe fehlerhaft sein kann immer noch. Dies ist enttäuschend und sollte IMO korrigiert werden. Danke noch einmal.
kkaszub
0

Ich habe diese kurzen Wege gefunden:

ls -p uploads | grep -Ev '/'

oder

ls -pIt_* uploads | grep -v /
Radu Rădeanu
quelle
-1

Probieren Sie diesen Alias ​​aus und verwenden Sie ihn:

alias l='ls -hLlF'
Körnig
quelle
ls -hLlFzeigt die Unterverzeichnisse und die Dateien, die mit beginnen t_. Wie beantwortet das die Frage?
Raphael Ahrens
Vielleicht habe ich die Frage falsch verstanden. ls -hLlF zeigt die Zielverzeichnisse der verknüpften Verzeichnisse nicht an.
Granular
Scheint so. Aber hast du nicht die anderen Antworten auf die Frage gelesen?
Raphael Ahrens
-1

Kinderleicht:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

Gräber
quelle
(1) Diese Antwort ist so einfach, dass sie schon einmal gegeben wurde. (2) Warum müssen Sie Ihrer Meinung nach den vollständigen Pfad zum Verzeichnis angeben?
Scott
@Scott - Dies ist ein sehr schneller und einfacher Weg zur Lösung. Der vollständige Pfad wurde angegeben, um die Antwort universell zu machen ...
Digger