Wie liste ich alle Dateien in einem Verzeichnis auf, mit Ausnahme der Dateien mit den angegebenen Erweiterungen?

28

Angenommen, ich habe einen Ordner mit TXT- , PDF- und anderen Dateien. Ich möchte die "anderen" Dateien auflisten (dh Dateien ohne die Endungen .txt oder .pdf ). Haben Sie Ratschläge dazu?

Ich weiß, wie man Dateien auflistet, die keine bestimmte Erweiterung haben. Wenn ich zum Beispiel alle Dateien mit Ausnahme der TXT- Dateien auflisten möchte , dann auch nicht

find -not -iname "*.txt"

oder

ls | grep -v '\.txt$' | column

scheinen zu funktionieren. Aber, wie kann ich Liste alles außer TXT - Dateien oder PDF - Dateien? Es scheint, dass ich eine Art logisches "oder" in findoder verwenden muss grep.

Andrew
quelle
2
Bedenken Sie, dass das Verhalten von lsvs findvs globbing für versteckte Punktedateien unterschiedlich sein kann.
jw013
1
Eine andere Sache, die Sie beachten sollten: findUnterverzeichnisse werden wie rekursiv durchlaufen ls. Verwenden Sie -maxdepth 1mit find, um das Verhalten zu verbessern ls.
jw013,
Also nicht rekursiv, sondern nur die Dateien im aktuellen Verzeichnis auflisten?
Daisy

Antworten:

28

Vorausgesetzt, man hat eine entsprechende Version von ls, ist dies möglicherweise der einfachste Weg:

ls -I "*.txt" -I "*.pdf"

Wenn Sie alle Unterverzeichnisse durchlaufen möchten:

ls -I "*.txt" -I "*.pdf" -R
Dejian
quelle
8
GNU- lsOptionen sind nicht portierbar.
Bahamat
4
lsgehört sowieso nicht wirklich in tragbare Skripte, daher gehe ich davon aus, dass das OP nur nach der interaktiven Verwendung fragt.
jw013
1
Warum ist es nicht tragbar? Was soll ich dann verwenden?
Freedo
28

Finden Sie Unterstützungen -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

Sie benötigen die Klammer, um den Vorrang richtig zu machen. Finden macht eine Menge Sachen; Ich schlage vor, die Manpage durchzulesen.

Sie können auch ein oder in grep(aber eigentlich sollten Sie die Ausgabe von nicht analysierenls )

ls | grep -Ev '\.(txt|pdf)$' | column
derobert
quelle
1
Vielen Dank! Warum sollte ich die Ausgabe von nicht analysieren ls?
Andrew
6
@Andrew zuerst, weil es zerbrechlich ist (betrachten Sie einen Dateinamen mit einem Zeilenumbruch - ja, das ist ein gültiger Dateiname - suchen Sie nach -print0 / -exec / -delete / etc. Um dieses Problem zu vermeiden); zweitens, weil es normalerweise einen einfacheren Weg gibt.
Derobert
Neben der findManpage empfehle ich von ganzem Herzen die Artikel zu Unix Power Tools find, wie docstore.mik.ua/orelly/unix3/upt/ch09_06.htm und docstore.mik.ua/orelly/unix3/upt/ch09_12.htm
Wildcard
Nur um die Aussage für den Menschen zu entschlüsseln:find . NOT ( *.txt OR *.pdf )
wisbucky
12

Bei basherweitertem Globbing (einschalten mit shopt -s extglob) sollte der Glob !(*.txt|*.pdf)funktionieren. Sie können diesen Glob direkt an jeden Befehl übergeben, der Dateiargumente akzeptiert, einschließlich, aber nicht beschränkt auf ls.

jw013
quelle
1
+1 Wenn Sie jedoch Unterverzeichnisse haben, wird auch deren Inhalt aufgelistet. Verwenden Sie -d, um dies zu vermeiden:ls -d !(*.txt|*.pdf)
legends2k
Vielen Dank, ich habe genau nach der Syntax gesucht, um mehrere Dateien zu akzeptieren. Dies würde hier gut
Freedo
6

In zshmit extendedglob:

print -rl -- *~*.(txt|pdf)

oder

print -rl -- ^*.(txt|pdf)

Oder mit kshglob(ja, das ist ksh globbing nicht "bash extended globbing"):

print -rl -- !(*.txt|*.pdf)

Denken Sie jedoch daran, dass diese auch Punktedateien ausschließen.

ksh93 hat das FIGNORE(mis) -Feature:

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *
Thor
quelle
4
find /path/to/directory '!' -name '*.pdf' '!' -name '*.txt'

Dies entspricht aufgrund der Gesetze von De Morgan dem Befehl mit dem Operator OR .

Francesco Turco
quelle
3

Wie von derobert vorgeschlagen, ist Ihre beste Wette zu verwenden find. Sie können das Ergebnis jedoch auch in einer Pipeline mit anderen Befehlen verwenden.

GNU (und einige BSDs) findunterstützen das -print0Prädikat, das angibt, den Dateinamen zu drucken, der mit einem NUL- Zeichen abgeschlossen ist. Dieses Zeichen ist in einem Dateinamen nicht zulässig und garantiert, dass es nicht zu einer Kollision kommt. Andere Befehle können angewiesen werden, die NUL als Eingabebegrenzer zu verwenden.

Das wichtigste davon ist GNU xargs, das den von Ihnen angegebenen Befehl ausführt und ihm die Liste der Dateien als Befehlszeilenargumente übergibt. Sie möchten xargs -r0zusammen mit find's ausgeführt werden. -print0Zum Beispiel:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

Dies druckt sicher ein langes Verzeichnis aller von der Anzeige pdf und txt - Dateien, einschließlich diejenigen mit Leerzeichen oder nicht druckbare Zeichen im Namen.

Sie können es auch mit GNU tarwie folgt verwenden:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

Dadurch wird eine tar.gz-Datei mit allen Dateien erstellt, deren Namen nicht mit .tar.gz enden

rsyncAkzeptiert auch null-getrennte Dateien mit dem -0Parameter, wie auch einige andere. Aber xargsist der Kleber, den Sie normalerweise für diese Art von Zweck verwenden. Entweder das oder find's -execFeature.

tylerl
quelle
Das tarBefehlsbeispiel ist gut. Für die meisten Zwecke -execist jedoch eine bessere Passform.
Wildcard
1

Wenn Sie kein Unterverzeichnis haben

ls !(*.pdf|*.txt)

sollte auch funktionieren!

Aber

ls -I "*.pdf" -I "*.txt"

ist der übliche Weg.

abu_bua
quelle
0

Wenn Sie eine bash-kompatible Shell verwenden, können Sie außerdem die Variable GLOBIGNORE verwenden, um Wiederholungen vom Mustervergleich auszuschließen. Vom mann:

   GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames
          to be ignored by pathname expansion.  If a filename matched by a
          pathname  expansion  pattern also matches one of the patterns in
          GLOBIGNORE, it is removed from the list of matches.

In Ihrem speziellen Fall:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

Bitte beachten Sie, dass ich diesen Befehl als Sub-Shell (in Klammern) ausführe, um die GLOBIGNORE-Umgebungsvariable meiner interaktiven Shell nicht zu ändern.

Sylvain Leroux
quelle