Ich versuche, einen if
zu schreiben -Anweisung, um zu testen, ob es Dateien gibt, die einem bestimmten Muster entsprechen. Wenn sich in einem Verzeichnis eine Textdatei befindet, sollte ein bestimmtes Skript ausgeführt werden.
Mein Code derzeit:
if [ -f /*.txt ]; then ./script fi
Bitte geben Sie einige Ideen; Ich möchte das Skript nur ausführen, wenn es eine .txt
gibt im Verzeichnis.
Akzeptierte Antwort:
[ -f /*.txt ]
würde nur dann true zurückgeben, wenn eins vorhanden ist (und nur eine) nicht versteckte Datei in /
dessen Name auf .txt
endet und ob diese Datei eine reguläre Datei oder ein Symlink zu einer regulären Datei ist.
Das liegt daran, dass Wildcards von der Shell erweitert werden, bevor sie an den Befehl übergeben werden (hier [
).
Also, wenn es eine /a.txt
gibt und /b.txt
, [
Es werden 5 Argumente übergeben:[
, -f
, /a.txt
, /b.txt
und ]
. [
würde dann das -f
beanstanden hat zu viele Argumente.
Wenn Sie überprüfen möchten, ob die *.txt
Muster wird in der bash
auf mindestens eine nicht versteckte Datei (regulär oder nicht) erweitert Schale:
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "[email protected]" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
ist bash
spezifisch (shopt
ist nullglob
kommt eigentlich von zsh
), sondern Shells wie ksh93
, zsh
, yash
, tcsh
äquivalente Anweisungen haben.
Mit zsh
, der Test für Gibt es Dateien, die einem Muster entsprechen kann mit einer anonymen Funktion und dem N
geschrieben werden (für nullglob
) und Y1
(um nach dem ersten Fund zu stoppen) Glob Qualifier:
if ()(($#)) *.txt(NY1); then
do-something
fi
Beachten Sie, dass diese Dateien durch Lesen des Inhalts des Verzeichnisses gefunden werden. Es versucht überhaupt nicht, auf diese Dateien zuzugreifen, was es effizienter macht als Lösungen, die Befehle wie ls
aufrufen oder stat
auf dieser von der Shell berechneten Liste von Dateien.
Das standardmäßige sh
Äquivalent wäre:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "[email protected]"
esac
Das Problem ist, dass bei Bourne- oder POSIX-Shells ein Muster, das nicht übereinstimmt, auf sich selbst erweitert wird. Also wenn *.txt
erweitert sich zu *.txt
, Sie wissen nicht, ob es daran liegt, dass es keine .txt
gibt Datei im Verzeichnis oder weil es eine Datei namens *.txt
gibt . Mit [*].txt *.txt
erlaubt, zwischen den beiden zu unterscheiden.
Wenn Sie nun überprüfen möchten, ob die *.txt
stimmt mit mindestens einem regulären überein Datei oder symbolischer Link zu einer regulären Datei (wie Ihr [ -f *.txt ]
schlägt vor, was Sie tun möchten), oder dass alle Dateien, die mit *.txt
übereinstimmen, angezeigt werden sind normal Dateien (nach Symlink-Auflösung), das ist wieder eine andere Sache.
Mit zsh
:
if ()(($#)) *.txt(NY1-.); then
echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
echo "there is at least one non-regular .txt files"
fi
(Entfernen Sie den -
wenn Sie den Test vor der Symlink-Auflösung durchführen möchten, betrachten Sie Symlinks als nicht reguläre Dateien, unabhängig davon, ob sie auf reguläre Dateien verweisen oder nicht).