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.


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

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

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.


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' *


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.


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.


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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.