Wie überprüfe ich anhand eines Shell-Skripts, ob ein Verzeichnis Dateien enthält?
Ähnliches
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
Dies funktioniert jedoch, wenn das Verzeichnis eine oder mehrere Dateien enthält (die obige Datei funktioniert nur mit genau 0 oder 1 Dateien).
Antworten:
Die bisherigen Lösungen nutzen
ls
. Hier ist eine All-Bash-Lösung:quelle
shopt -q nullglob || resetnullglob=1; shopt -s nullglob; shopt -q dotglob || resetdotglob=1; shopt -s dotglob; files=(/some/dir/*); [ "$files" ] && echo "wowzers"; [ "$resetdotglob" ] && shopt -u dotglob; [ "$resetnullglob" ] && shopt -u nullglob;
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
Dann sollte sich die if-Anweisung in ändernif [ ${#files} -gt 0 ];
oder haben Sie einfach das () um den Sub-Shell-Befehl vergessen?files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
Drei beste Tricks
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
Dieser Trick ist 100%
bash
und ruft eine Sub-Shell auf (erzeugt sie). Die Idee stammt von Bruno De Fraine und wurde durch den Kommentar von Teambob verbessert .Hinweis: Kein Unterschied zwischen einem leeren und einem nicht vorhandenen Verzeichnis (und selbst wenn der angegebene Pfad eine Datei ist).
Es gibt eine ähnliche Alternative und weitere Details (und weitere Beispiele) in den 'offiziellen' FAQ für den # bash IRC-Kanal :
[ -n "$(ls -A your/dir)" ]
Dieser Trick ist von dem 2007 veröffentlichten Artikel von nixCraft inspiriert . Hinzufügen
2>/dev/null
, um den Ausgabefehler zu unterdrücken"No such file or directory"
.Siehe auch Andrew Taylors Antwort (2008) und gr8can8dians Antwort (2011).
oder die einzeilige Bashism-Version:
Hinweis:
ls
Gibt zurück,$?=2
wenn das Verzeichnis nicht vorhanden ist. Aber kein Unterschied zwischen einer Datei und einem leeren Verzeichnis.[ -n "$(find your/dir -prune -empty)" ]
Dieser letzte Trick ist inspiriert von der Antwort von gravstar, bei der
-maxdepth 0
er durch den Kommentar-prune
von phils ersetzt und verbessert wird .eine Variation mit
-type d
:Erläuterung:
find -prune
ist ähnlich wiefind -maxdepth 0
mit weniger Zeichenfind -empty
druckt die leeren Verzeichnisse und Dateienfind -type d
druckt nur VerzeichnisseHinweis: Sie können auch
[ -n "$(find your/dir -prune -empty)" ]
nur die folgende Kurzversion ersetzen :Dieser letzte Code funktioniert in den meisten Fällen, aber beachten Sie, dass böswillige Pfade einen Befehl ausdrücken können ...
quelle
[ -n "$(find "your/dir" -prune -empty)" ]
, um die Wiederholung des Verzeichnispfads zu vermeiden.if [ ``ls -A your/dir`` ]
in einem Skript bin ich zu dem Schluss gekommen, dass es für ein Verzeichnis mit 0, 1 oder 2 Unterverzeichnissen gut funktioniert, für ein Verzeichnis mit mehr als 2 Unterverzeichnissen jedoch fehlschlägt.line 17: [: 20150424-002813: unary operator expected
Wo20150424-002813
war einer der Verzeichnisnamen? Die benutzte Schale war/bin/bash/
. Ich habe es schließlich geändert inls "$destination" | tail -1
if [ ``ls -A my/dir`` ]
geht bei Irrtum ausbash: [: -A: binary operator expected
. Getestet mit den Bash-Versionen 4.1.2 und 4.2.53.-n
Variante in der Überschrift stand, dann aber nicht im folgenden Absatz). Also ja, es ist in Ordnung.ls: cannot access '/path': No such file or directory
. Gibt es eine Möglichkeit, diese Nachricht zu unterdrücken? Ich würde dort gerne still scheitern.Wie wäre es mit folgendem:
Auf diese Weise muss keine vollständige Liste des Inhalts des Verzeichnisses erstellt werden. Die
read
beiden ist die Ausgabe zu verwerfen und machen den Ausdruck auswerten nur wahr , wenn etwas gelesen wird (dh/some/dir/
leer durch gefundenfind
).quelle
find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
ls
Ausgabe und ist nicht auf nicht standardmäßige Shell-Funktionen angewiesen.-maxdepth
und-empty
Primärfarben.Versuchen:
quelle
/bin/ls <some_dir>/* 2> /dev/null
if [! -z "$ tmp"]; dann echo Etwas ist da fils /some/dir/*
]; dann echo "huzzah"; fi-n
anstelle von verwenden! -z
(beide sind gleichwertig, aber warum nicht die kürzere Form verwenden, wenn sie vorhanden ist) ?BigGray% if [ ! -z
ls / some / dir / * `]; dann echo "huzzah"; fi zsh: keine Übereinstimmungen gefunden: / some / dir / * `ls...
in Bashquelle
Achten Sie auf Verzeichnisse mit vielen Dateien! Die Auswertung des
ls
Befehls kann einige Zeit dauern .IMO ist die beste Lösung die, die verwendet
quelle
quelle
Könnten Sie die Ausgabe davon vergleichen?
quelle
Einige Implementierungshinweise:
for
Schleife vermeidet einen Aufruf eines externenls
Prozesses. Es werden immer noch alle Verzeichniseinträge einmal gelesen. Dies kann nur durch Schreiben eines C-Programms optimiert werden, das readdir () explizit verwendet.test -e
Innere der Schleife fängt den Fall eines leeren Verzeichnisses ab. In diesem Fall würde der Variablen_ief
der Wert "somedir / *" zugewiesen. Nur wenn diese Datei vorhanden ist, gibt die Funktion "nicht leer" zurück.test
Implementierung unterstützt das-e
Flag nicht.quelle
dotglob
nicht gesetzt ist -shopt -s dotglob
Dies sagt mir, ob das Verzeichnis leer ist oder nicht, wie viele Dateien es enthält.
quelle
ls
.Dies mag eine sehr späte Antwort sein, aber hier ist eine Lösung, die funktioniert. Diese Zeile erkennt nur das Vorhandensein von Dateien! Es gibt kein falsches Positiv, wenn Verzeichnisse vorhanden sind.
quelle
Angenommen , Sie nicht über eine Datei mit dem Namen haben
*
in/any/dir/you/check
, sollte es funktionieren aufbash
dash
posh
busybox sh
undzsh
aber (für zsh) erfordernunsetopt nomatch
.Die Leistung sollte mit jeder
ls
Verwendung vergleichbar sein*
(glob). Ich denke, sie wird in Verzeichnissen mit vielen Knoten langsam sein (meine/usr/bin
mit mehr als 3000 Dateien waren nicht so langsam). Sie wird mindestens genug Speicher verwenden, um alle Verzeichnisse / Dateinamen (und mehr) zuzuweisen. Da sie alle als Argumente an die Funktion übergeben (aufgelöst) werden, haben einige Shell wahrscheinlich Grenzen für die Anzahl der Argumente und / oder die Länge der Argumente.Eine tragbare schnelle O (1) Null-Ressourcen-Methode, um zu überprüfen, ob ein Verzeichnis leer ist, wäre schön.
aktualisieren
Die obige Version berücksichtigt keine versteckten Dateien / Verzeichnisse, falls weitere Tests erforderlich sind, wie die Tricks
is_empty
von Rich's sh (POSIX-Shell) :Aber stattdessen denke ich über so etwas nach:
Einige Bedenken hinsichtlich nachlaufender Schrägstriche, die sich vom Argument und der Suchausgabe unterscheiden, wenn das Verzeichnis leer ist, und nachgestellten Zeilenumbrüchen (dies sollte jedoch einfach zu handhaben sein), leider in meiner
busybox
sh
Show, was wahrscheinlich ein Fehler in derfind -> dd
Pipe ist, bei dem die Ausgabe zufällig abgeschnitten wurde ( Wenn ich verwendet habe, istcat
die Ausgabe immer die gleiche, scheintdd
mit dem Argument zu seincount
).quelle
is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
ZSH
Ich weiß, dass die Frage für Bash markiert wurde; aber nur als Referenz für zsh- Benutzer:
Test auf nicht leeres Verzeichnis
So überprüfen Sie, ob
foo
es nicht leer ist:Wenn
foo
nicht leer, wird der Code imfor
Block ausgeführt.Test auf leeres Verzeichnis
So überprüfen Sie, ob
foo
es leer ist:Wenn
foo
leer, wird der Code imfor
Block ausgeführt.Anmerkungen
Wir mussten das
foo
obige Verzeichnis nicht zitieren , aber wir können dies tun, wenn wir:Wir können auch mehr als ein Objekt testen, auch wenn es kein Verzeichnis ist:
Alles, was kein Verzeichnis ist, wird einfach ignoriert.
Extras
Da wir globben, können wir jeden Glob (oder jede Klammererweiterung) verwenden:
Wir können auch Objekte untersuchen, die in einem Array platziert sind. Mit den Verzeichnissen wie oben zum Beispiel:
Auf diese Weise können wir Objekte testen, die möglicherweise bereits in einem Array-Parameter festgelegt sind.
Beachten Sie, dass der Code im
for
Block offensichtlich nacheinander in jedem Verzeichnis ausgeführt wird. Wenn dies nicht wünschenswert ist, können Sie einfach einen Array-Parameter auffüllen und dann diesen Parameter bearbeiten:Erläuterung
Für zsh-Benutzer gibt es das
(F)
Glob-Qualifikationsmerkmal (sieheman zshexpn
), das mit "vollständigen" (nicht leeren) Verzeichnissen übereinstimmt:Das Qualifikationsmerkmal
(F)
listet übereinstimmende Objekte auf: ist ein Verzeichnis UND ist nicht leer. Also,(^F)
stimmt überein: kein Verzeichnis ODER ist leer. So(^F)
würde allein beispielsweise auch reguläre Dateien aufgelistet. Wie auf derzshexp
Manpage erläutert , benötigen wir daher auch das(/)
Glob-Qualifikationsmerkmal, das nur Verzeichnisse auflistet:Um zu überprüfen, ob ein bestimmtes Verzeichnis leer ist, können Sie Folgendes ausführen:
und nur um sicherzugehen, dass ein nicht leeres Verzeichnis nicht erfasst wird:
Hoppla! Da
Y
zsh nicht leer ist, findet zsh keine Übereinstimmungen für(/^F)
("Verzeichnisse, die leer sind") und gibt daher eine Fehlermeldung aus, dass keine Übereinstimmungen für den Glob gefunden wurden. Wir müssen daher diese möglichen Fehlermeldungen mit dem(N)
Glob-Qualifikationsmerkmal unterdrücken :Für leere Verzeichnisse benötigen wir daher das Qualifikationsmerkmal
(N/^F)
, das Sie wie folgt lesen können: "Warnen Sie mich nicht vor Fehlern, Verzeichnissen, die nicht voll sind".Ebenso benötigen wir für nicht leere Verzeichnisse das Qualifikationsmerkmal
(NF)
, das wir ebenfalls lesen können: "Warnen Sie mich nicht vor Fehlern, vollständige Verzeichnisse".quelle
Ich bin überrascht, dass der Wooledge-Leitfaden für leere Verzeichnisse nicht erwähnt wurde. Dieser Leitfaden und wirklich alles von Wooledge ist ein Muss für Fragen zum Muscheltyp.
Bemerkenswert von dieser Seite:
quelle
Kleine Variation von Brunos Antwort :
Für mich geht das
quelle
Ich nehme einen Hinweis (oder mehrere) aus der Antwort von olibre und mag eine Bash-Funktion:
Denn während es eine Unterschale erstellt, kommt es einer O (1) -Lösung so nahe, wie ich es mir vorstellen kann, und wenn man ihr einen Namen gibt, ist sie lesbar. Ich kann dann schreiben
Was O (1) betrifft, gibt es Ausreißerfälle: Wenn in einem großen Verzeichnis alle oder alle bis auf den letzten Eintrag gelöscht wurden, muss "find" möglicherweise das Ganze lesen, um festzustellen, ob es leer ist. Ich glaube, dass die erwartete Leistung O (1) ist, aber im schlimmsten Fall ist die Verzeichnisgröße linear. Ich habe das nicht gemessen.
quelle
Bisher habe ich keine Antwort gesehen, die grep verwendet, was meiner Meinung nach eine einfachere Antwort geben würde (mit nicht zu vielen seltsamen Symbolen!). So würde ich mithilfe der Bourne-Shell überprüfen, ob Dateien im Verzeichnis vorhanden sind:
Dies gibt die Anzahl der Dateien in einem Verzeichnis zurück:
Sie können den Verzeichnispfad eingeben, in den das Verzeichnis geschrieben wurde. Die erste Hälfte der Pipe stellt sicher, dass das erste Zeichen der Ausgabe für jede Datei "-" ist. egrep zählt dann die Anzahl der Zeilen, die mit diesem Symbol beginnen, unter Verwendung regulärer Ausdrücke. Jetzt müssen Sie nur noch die Nummer speichern, die Sie erhalten, und sie mit Anführungszeichen wie den folgenden vergleichen:
x ist eine Variable Ihrer Wahl.
quelle
Ich mischte Pflaumensachen und letzte Antworten und musste
Das funktioniert auch für Pfade mit Leerzeichen
quelle
Einfache Antwort mit Bash :
quelle
Ich würde gehen für
find
:Dies überprüft die Ausgabe der Suche nach nur Dateien im Verzeichnis, ohne die Unterverzeichnisse zu durchlaufen. Anschließend wird die Ausgabe mit der folgenden
-z
Option überprüftman test
:Sehen Sie einige Ergebnisse:
Leeres Verzeichnis:
Nur dirs drin:
Eine Datei im Verzeichnis:
Eine Datei in einem Unterverzeichnis:
quelle
Mit einer Problemumgehung konnte ich auf einfache Weise herausfinden, ob sich Dateien in einem Verzeichnis befinden. Dies kann mit grep-Befehlen erweitert werden, um speziell XML- oder TXT-Dateien usw. zu überprüfen. Beispiel:
ls /some/dir | grep xml | wc -l | grep -w "0"
quelle
quelle
nullglob
, dies nicht zu verwenden, wenn Sie festlegen , da derls
Befehl dann erfolgreich ist.um ein bestimmtes Zielverzeichnis zu testen
quelle
Versuchen Sie es mit dem Befehl find. Geben Sie das Verzeichnis fest oder als Argument an. Starten Sie dann find, um alle Dateien im Verzeichnis zu durchsuchen. Überprüfen Sie, ob die Rückgabe des Funds null ist. Echo die Daten von find
quelle
Ich mag die veröffentlichten
ls - A
Lösungen nicht. Höchstwahrscheinlich möchten Sie testen, ob das Verzeichnis leer ist, weil Sie es nicht löschen möchten. Das Folgende macht das. Wenn Sie jedoch nur eine leere Datei protokollieren möchten, ist das Löschen und Neuerstellen dieser Datei sicherlich schneller als das Auflisten möglicherweise unendlicher Dateien?Das sollte funktionieren...
quelle
${target}/..
.Funktioniert gut für mich dies (wenn dir existiert):
Mit voller Kontrolle:
quelle