2 Stimmen

Bash testen einer Gruppe von Verzeichnissen auf Existenz

Dokumente sind in einem Dateisystem gespeichert, das "tägliche" Verzeichnisse enthält, z.B. 20050610. In einem Bash-Skript möchte ich die Dateien in einem Monat im Wert dieser Verzeichnisse auflisten. Daher führe ich einen Find-Befehl aus find /200506* -type f >> jun2005.lst. Möchte überprüfen, dass dieses Verzeichnisset nicht null ist, bevor ich den Find-Befehl ausführe. Wenn ich jedoch if[ -d 200506* ] verwende, erhalte ich einen "zu viele Argumente" Fehler. Wie kann ich das umgehen?

2voto

Dennis Williamson Punkte 322329

Ihr "zu viele Argumente" Fehler kommt nicht daher, dass es eine riesige Anzahl von Dateien gibt und das Limit für Befehlszeilenargumente überschritten wird. Es kommt daher, dass mehr als ein oder zwei Verzeichnisse mit dem Glob übereinstimmen. Ihr Glob "200506*" erweitert sich zu etwas wie "20050601 20050602 20050603..." und der -d Test erwartet nur ein Argument.

$ mkdir test
$ cd test
$ mkdir a1
$ [ -d a* ]    # kein Fehler
$ mkdir a2
$ [ -d a* ]
-bash: [: a1: binärer Operator erwartet
$ mkdir a3
$ [ -d a* ]
-bash: [: zu viele Argumente

Die Antwort von zed_0xff ist auf dem richtigen Weg, aber ich würde einen anderen Ansatz verwenden:

shopt -s nullglob
path='/pfad/zu/verzeichnissen'
glob='200506*/'
outfile='jun2005.lst'
dirs=("$path"/$glob)  # dirs ist ein Array, das bei Bedarf iteriert werden kann
if (( ${#dirs[@]} > 0 ))
then
    echo "Verzeichnisse gefunden"
    # append ist hier möglicherweise nicht notwendig 
    find "$path"/$glob -type f >> "$outfile"
fi

Die Position der Anführungszeichen in "$path"/$glob gegenüber "$path/$glob" ist entscheidend dafür, dass dies funktioniert.

Bearbeitung:

Korrekturen wurden vorgenommen, um Dateien auszuschließen, die dem Glob entsprechen (so dass nur Verzeichnisse eingeschlossen sind) und um mit dem sehr ungewöhnlichen Fall eines Verzeichnisses umzugehen, das buchstäblich wie der Glob benannt ist ("200506*").

1voto

Jürgen Hötzel Punkte 17196
prefix="/tmp/path"
glob="200611*"
n_dirs=$(find $prefix -maxdepth 1 -type d -wholename "$prefix/$glob" |wc -l)
if [[ $n_dirs -gt 0 ]];then 
   find $prefix -maxdepth 2 -type f -wholename "$prefix/$glob" 
fi

0voto

zed_0xff Punkte 31060
S=200506*

if [ ${#S} -gt 6 ]; then
    echo haz filez!
else
    echo no filez
fi

Keine sehr elegante, aber ohne externe Hilfsmittel/Befehle (wenn "[" nicht als extern angesehen wird)

Der Hinweis ist, dass, wenn einige Dateien übereinstimmen, die "S"-Variable deren Namen mit Leerzeichen getrennt enthält. Andernfalls enthält es den String "200506*" selbst.

0voto

Bobby Punkte 11139

Sie könnten ls so verwenden:

  if [ -n "$(ls -d | grep 200506)" ]; then
        # Es gibt Verzeichnisse mit diesem Muster
  fi

0voto

TerryP Punkte 1062

Weil es in den meisten Shells eine Begrenzung der Befehlszeilenlänge gibt: Alles wie "$(ls -d | grep 200506)" oder /path/200506* läuft Gefahr, die Grenze zu überschreiten. Ich bin mir nicht sicher, ob Substitutionen und Globus-Erweiterungen in BASH dazu zählen, aber ich vermute es. Sie müssten es testen und die Bash-Dokumentation und den Quellcode überprüfen, um sicher zu gehen.

Die Antwort liegt in der Vereinfachung Ihrer Frage.

find /200506* -type f -exec somescript '{}' \;

Wo somescript ein Shell-Skript ist, das den Test durchführt. Vielleicht etwas wie folgt:

#!/bin/sh
[ -d "$@" ] && echo "$@" >> june2005.lst

Das Übergeben der june2005.lst an das Skript (Rat: Verwenden Sie eine Umgebungsvariable) und der Umgang mit der Möglichkeit, dass sich 200506* zu einem zu großen Dateipfad ausweiten kann, bleibt als Übung für den OP ;)

Die Integration des gesamten Vorgangs in eine Pipeline oder die Anpassung einer allgemeineren Skriptsprache würde Leistungssteigerungen bringen, indem die Anzahl der gestarteten Shells minimiert wird. Das wäre spaßig. Hier ist ein Hinweis dazu, verwenden Sie -exec und ein anderes Programm (awk, perl, etc.), um den Verzeichnistest als Teil eines Einzeilers zu machen, und behalten Sie das >>june2005.lst in dem find-Befehl bei.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X