Ich möchte testen, ob ein Verzeichnis keine Dateien enthält. In diesem Fall überspringe ich die Verarbeitung.
Ich habe folgendes versucht:
if [ ./* == "./*" ]; then
echo "No new file"
exit 1
fi
Das gibt den folgenden Fehler:
line 1: [: too many arguments
Gibt es eine Lösung / Alternative?
Antworten:
Es wäre auch cool, vorher zu prüfen, ob das Verzeichnis existiert.
quelle
&&
und||
gleichzeitig! Wennecho "Not Empty"
fehlschlägt,echo "Empty"
wird ausgeführt! Versuchen Sie esecho "test" && false || echo "fail"
! Ja, ich weiß,echo
wird nicht scheitern, aber wenn Sie einen anderen Befehl ändern, werden Sie überrascht sein![ "$(ls -A /)" ] && touch /non-empty || echo "Empty"
- Wenn Sie die nicht leeren Verzeichnisse mit einer erstellten Datei mit dem Namen "markieren" möchtennon-empty
, schlägt dies fehl und es wird "Leer" gedruckt.touch /empty
in meiner leitungif [ -n "$(ls -A /path/to/dir)" ]; then
... Bitte aktualisieren Sie die Antwort, bevor jemand diesen Code irgendwo auf seinem Server einfügt und ein Hacker herausfindet, wie er ihn ausnutzen kann. Wenn/path/to/dir
nicht leer, werden die Dateinamen dort als Argumente übergeben, an/bin/test
die eindeutig nicht gedacht ist. Fügen Sie einfach das-n
Argument hinzu, das Problem ist gelöst. Vielen Dank!Keine Notwendigkeit, irgendetwas zu zählen oder Muschelkugeln. Sie können auch
read
in Kombination mit verwendenfind
. Wennfind
die Ausgabe leer ist, geben Sie Folgendes zurückfalse
:Dies sollte tragbar sein.
quelle
echo
Anrufe spiegeln das falsche Ergebnis wider: In meinem Test (unter Cygwin)find . -mindepth 1 | read
hatte ein 141 Fehlercode in einem nicht leeren Verzeichnis und 0 in einem leeren Verzeichnisread
0 und für ein leeresset -o pipefail
quelle
-n
, um korrekt und sicher zu sein (Test mit einem Verzeichnis mit Leerzeichen im Namen, Test mit einem nicht leeren Verzeichnis mit dem Namen '0 = 1').... [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; ...
grep
. serverfault.com/questions/225798/…find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty | grep .
und sich auf den Exit-Status von grep zu verlassen. Was auch immer Sie tun, dies ist die richtige Antwort auf diese Frage.quelle
Dies erledigt die Arbeit im aktuellen Arbeitsverzeichnis (.):
oder derselbe Befehl wurde in drei Zeilen aufgeteilt, um die Lesbarkeit zu verbessern:
Ersetzen Sie einfach
ls -1A . | wc -l
mit ,ls -1A <target-directory> | wc -l
wenn Sie benötigen sie auf einem anderen Zielordner auszuführen.Edit : Ich habe ersetzt
-1a
durch-1A
(siehe @ Daniel Kommentar)quelle
ls -A
stattdessen. Einige Dateisysteme nicht haben.
und..
symbolische Links nach der docs.-1
ist definitiv überflüssig. Auch wennls
beim Pipe-Druck nicht ein Element pro Zeile gedruckt wird, hat dies keinen Einfluss auf die Idee, zu überprüfen, ob null oder mehr Zeilen erzeugt wurden.Verwenden Sie Folgendes:
Auf diese Weise sind Sie unabhängig vom Ausgabeformat von
ls
.-mindepth
Überspringt das Verzeichnis selbst und-maxdepth
verhindert die rekursive Verteidigung in Unterverzeichnissen, um die Arbeit zu beschleunigen.quelle
wc -l
undfind
Ausgabeformat (was aber einigermaßen klar ist).Verwenden eines Arrays:
quelle
shopt -s nullglob
${#files[@]} == 2
Annahme steht nicht für das Stammverzeichnis (Sie werden wahrscheinlich nicht testen, ob es leer ist, aber ein Code, der diese Einschränkung nicht kennt, könnte dies tun).Eine hackige, aber nur bash-freie PID-Methode:
Dies macht sich die Tatsache zunutze, dass
test
builtin mit 2 endet, wenn nach mehr als einem Argument Folgendes angegeben wird-e
: Zunächst wird"$1"/*
glob um bash erweitert. Dies führt zu einem Argument pro Datei. DamitWenn keine Dateien vorhanden sind, wird das Sternchen in
test -e "$1"*
nicht erweitert, sodass Shell auf die angegebene Datei zurückgreift*
, die 1 zurückgibt.... außer wenn es tatsächlich eine Datei gibt, die genau benannt ist
*
, wird das Sternchen zu "Sternchen" erweitert, was zum selben Aufruf wie oben führt, d. h.test -e "dir/*"
, nur dieses Mal wird 0 zurückgegeben. (Vielen Dank an @TrueY für den Hinweis.)Wenn es eine Datei gibt,
test -e "dir/file"
wird ausgeführt, was 0 zurückgibt.Wenn aber mehr Dateien als 1 vorhanden sind,
test -e "dir/file1" "dir/file2"
wird ausgeführt, was die Bash als Verwendungsfehler meldet, dh 2.case
Wickelt die gesamte Logik so um, dass nur der erste Fall mit 1 Exit-Status als Erfolg gemeldet wird.Mögliche Probleme, die ich nicht überprüft habe:
Es gibt mehr Dateien als die Anzahl der zulässigen Argumente - ich schätze, dies könnte sich ähnlich verhalten wie bei 2+ Dateien.
Oder es gibt tatsächlich eine Datei mit einem leeren Namen - ich bin mir nicht sicher, ob dies unter einem vernünftigen OS / FS möglich ist.
quelle
test -e dir/*
wird aufgerufen. Wenn die einzige Datei '*' in dir ist, gibt test 0 zurück. Wenn es mehr Dateien gibt, gibt es 2 zurück. So funktioniert es wie beschrieben.Mit FIND (1) (unter Linux und FreeBSD) können Sie einen Verzeichniseintrag über "-maxdepth 0" nicht-rekursiv betrachten und mit "-empty" prüfen, ob er leer ist. Angewandt auf die Frage ergibt sich:
quelle
Ich denke die beste Lösung ist:
Vielen Dank an https://stackoverflow.com/a/91558/520567
Dies ist eine anonyme Bearbeitung meiner Antwort, die möglicherweise für jemanden hilfreich ist oder nicht: Eine geringfügige Änderung gibt die Anzahl der Dateien an:
Dies funktioniert auch dann einwandfrei, wenn Dateinamen Leerzeichen enthalten.
quelle
EDIT: Ich denke, dass diese Lösung mit gnu find gut funktioniert, nach einem kurzen Blick auf die Implementierung . Dies funktioniert jedoch möglicherweise nicht, wenn beispielsweise netbsd gefunden wird . In der Tat wird das Feld st_size von stat (2) verwendet. Das Handbuch beschreibt es als:
Eine bessere und auch einfachere Lösung ist:
Auch der -prune in der 1. Lösung ist unbrauchbar.
EDIT: no -exit für gnu find .. die obige Lösung ist gut für NetBSD's find. Für GNU find sollte dies funktionieren:
quelle
-exit
Prädikat .Das ist alles großartiges Zeug - habe es einfach in ein Skript geschafft, damit ich nach leeren Verzeichnissen unterhalb des aktuellen Verzeichnisses suchen kann. Das Folgende sollte in eine Datei namens 'findempty' geschrieben werden, die sich irgendwo im Pfad befindet, damit bash sie finden und dann chmod 755 ausführen kann. Kann leicht an Ihre spezifischen Bedürfnisse angepasst werden, denke ich.
quelle
Diese Arbeit für mich, um Dateien im Verzeichnis zu prüfen und zu verarbeiten
../IN
, wenn man bedenkt, dass sich das Skript im../Script
Verzeichnis befindet:quelle
Was ist mit dem Testen, ob ein Verzeichnis vorhanden und in einer if-Anweisung nicht leer ist?
quelle
Bei jedem anderen Verzeichnis als dem aktuellen können Sie überprüfen, ob es leer ist, indem Sie es versuchen
rmdir
, da diesrmdir
bei nicht leeren Verzeichnissen garantiert fehlschlägt. Wenn diesrmdir
gelingt und Sie tatsächlich wollten, dass das leere Verzeichnis den Test überlebt,mkdir
wiederholen Sie es einfach .Verwenden Sie diesen Hack nicht, wenn es andere Prozesse gibt, die durch ein Verzeichnis, von dem sie wissen, dass es kurzzeitig aufhört zu existieren, möglicherweise unübersichtlich werden.
Wenn dies bei
rmdir
Ihnen nicht funktioniert und Sie möglicherweise Verzeichnisse testen, die möglicherweise eine große Anzahl von Dateien enthalten, kann jede Lösung, die auf Shell-Globbing beruht, langsam werden und / oder zu Längenbeschränkungen für die Befehlszeile führen. Wahrscheinlich besserfind
in diesem Fall zu verwenden. Die schnellstefind
Lösung, die mir einfällt, geht soDies funktioniert für die GNU- und BSD-Versionen,
find
jedoch nicht für die Solaris- Versionen , bei denen jeder einzelne dieserfind
Operatoren fehlt . Liebe deine Arbeit, Oracle.quelle
Sie können versuchen, das Verzeichnis zu entfernen und auf einen Fehler zu warten. rmdir löscht das Verzeichnis nicht, wenn es nicht leer ist.
quelle
rmdir
schlägt fehl, wenn ich keine Berechtigung zum Entfernen des Verzeichnisses habe. oder wenn es ein Btrfs-Subvolume ist; oder wenn es zu einem schreibgeschützten Dateisystem gehört. Und wennrmdir
nicht fehlschlägt undmkdir
läuft: Was, wenn das bereits entfernte Verzeichnis einem anderen Benutzer gehörte? Was ist mit seinen (möglicherweise nicht standardmäßigen) Berechtigungen? ACL? erweiterte Attribute? Alles verloren.