Überprüfen Sie, ob ein bestimmter Dateityp / eine bestimmte Dateierweiterung im Verzeichnis vorhanden ist

80

Wie würden Sie mit bash feststellen, ob Dateien einer bestimmten Erweiterung in einem Verzeichnis vorhanden sind?

Etwas wie

if [ -e *.flac ]; then 
echo true; 
fi 
Wurlitzer
quelle

Antworten:

100
#!/bin/bash

count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then 
echo true
fi 
JeremyWeir
quelle
9
Hey Thomas, wie wäre es mit einer besseren Lösung für die Frage anstatt nur einer Abwertung.
JeremyWeir
8
Auch Thomas, Ihr Beispiel, warum man es nicht benutzt, benutzt ls -l, meine Antwort benutztls -1
JeremyWeir
10
Und diese Antwort analysiert nicht die Ausgabe, sondern nur die Zeilenausgabe, und ich bin mir fast sicher, dass selbst wenn ein Dateiname seltsame Zeichen enthält, ls -1eine Zeile pro Datei
gedruckt wird
2
Das Zählen von Zeilen wird analysiert. Und es wird eine falsche Nummer zurückgegeben, wenn Dateien enthalten \n(und ja, das ist in Dateinamen gültig).
Marcelm
Sagen Sie uns dann bitte, welcher magische Charakter im Namen einer Datei enthalten sein müsste, damit die Zeile nichts zählt.
Yeoman
27
#/bin/bash

myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then 
    echo true 
else 
    echo false
fi
wkl
quelle
5
Dieser ist schön, weil Sie tatsächlich etwas mit den Dateien tun können, nachdem Sie sie gefunden haben.
Ephsmith
+1 zum Umschließen der laufenden Unterschale find in Klammern, um myarray zu einer Arrayvariablen zu machen. Andernfalls, wenn find zurückgibt, entspricht kein Ergebnis ${#myarray[@]}1
shaffooo
könnte auch vereinfachen, indem Sie ls -1 *.pyanstelle von find
JrBenito
Wenn eine der Dateien ein Leerzeichen im Namen enthält, zählt eine Instanz als zwei.
Jon Griffith
15

Dies verwendet ls (1). Wenn keine flac-Dateien vorhanden sind, meldet ls einen Fehler und das Skript wird beendet. Andernfalls wird das Skript fortgesetzt und die Dateien können verarbeitet werden

#! /bin/sh
ls *.flac  >/dev/null || exit
## Do something with flac files here
Frayser
quelle
4
Für zusätzliche Stille leiten Sie auch 2> & 1 um.
Jasper
5
Die if-Version:if ls *.flac >/dev/null 2>&1; then ... fi;
Josiah Yoder
9
shopt -s nullglob
if [[ -n $(echo *.flac) ]]    # or [ -n "$(echo *.flac)" ]
then 
    echo true
fi
Bis auf weiteres angehalten.
quelle
3
#!/bin/bash
files=$(ls /home/somedir/*.flac 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
echo "Some files exists."
else
echo "No files with that extension."
fi
Ruel
quelle
3

Sie müssen vorsichtig sein, welche Flagge Sie in Ihre ifAussage werfen und wie sie sich auf das gewünschte Ergebnis bezieht.

Wenn Sie nur nach regulären Dateien und nicht nach anderen Arten von Dateisystemeinträgen suchen möchten, sollten Sie Ihr Codeskelett ändern in:

if [ -f file ]; then
echo true;
fi

Die Verwendung von -fbeschränkt sich ifauf reguläre Dateien, -eist jedoch umfangreicher und entspricht allen Arten von Dateisystemeinträgen. Es gibt natürlich auch andere Optionen wie -dfür Verzeichnisse usw. Eine gute Auflistung finden Sie unter http://tldp.org/LDP/abs/html/fto.html .

Wie von @msw hervorgehoben, wird test(dh [) ersticken, wenn Sie versuchen, mehr als ein Argument einzugeben . Dies kann in Ihrem Fall passieren, wenn der Glob für *.flacmehr als eine Datei zurückgegeben hat. Versuchen Sie ifin diesem Fall, Ihren Test in eine Schleife wie folgt zu verpacken :

for file in ./*.pdf
do
    if [ -f "${file}" ]; then
    echo 'true';
    break
    fi
done

Auf diese Weise können Sie breakbei der ersten Instanz der gewünschten Dateierweiterung mit dem Rest des Skripts fortfahren.

dtlussier
quelle
1
außer test(aka [) beschwert sich, wenn das Muster auf mehr als eine Datei erweitert wird: "Binäroperator erwartet" oder "zu viele Argumente"
msw
1
@msw - danke, ich habe nicht einmal an dieses Problem gedacht. Ich habe versucht, meine Antwort zu ändern, um sie zu berücksichtigen.
dtlussier
Sie sollten die Variable in Anführungszeichen setzen, dh verwenden "$file", da der Dateiname einige fehlerhafte Zeichen wie Leerzeichen oder Sternchen enthalten kann.
Roman Cheplyaka
3

Die Top-Lösung (if [ -e *.flac ];)hat bei mir nicht funktioniert.[: too many arguments

if ls *.flac >/dev/null 2>&1; dann wird es funktionieren.

Erik Buitenhuis
quelle
2
   shopt -s nullglob
   set -- $(echo *.ext)
    if [ "${#}" -gt 0 ];then
      echo "got file"
    fi
Ghostdog74
quelle
Das ist falsch. Erstens meinten Sie wahrscheinlich -gestattdessen -gt, weil Ihr Code sonst die einzelne Datei nicht erkennt. Zweitens, wenn keine Dateien vorhanden sind, die dem Muster entsprechen, bleibt die Zeichenfolge durch eine konforme Shell *.extunberührt, sodass Sie immer noch ein "Ergebnis" erhalten.
Roman Cheplyaka
$ # ist 1 für eine einzelne Datei und 0 für keine Dateien.
Frayser
2

Mit -f können Sie überprüfen, ob Dateien eines bestimmten Typs vorhanden sind:

#!/bin/bash

if [ -f *.flac ] ; then
   echo true
fi 
Uzi
quelle
Dies funktioniert, aber Sie begraben die Lede - der Grund dafür ist, dass die einzelne Klammer [(im Gegensatz zu der üblicheren [[) das Globbing nicht verhindert.
Adrian Petrescu
1

Nur Bash:

any_with_ext () ( 
    ext="$1"
    any=false
    shopt -s nullglob
    for f in *."$ext"; do
        any=true
        break
    done
    echo $any 
)

if $( any_with_ext flac ); then
    echo "have some flac"
else 
    echo "dir is flac-free"
fi

Ich verwende Klammern anstelle von geschweiften Klammern, um sicherzustellen, dass eine Unterschale verwendet wird (ich möchte Ihre aktuelle nullglobEinstellung nicht beeinträchtigen ).

Glenn Jackman
quelle
1

Hier ist eine Lösung, die keine externen Befehle (dh nein ls) verwendet, sondern stattdessen eine Shell-Funktion. In Bash getestet:

shopt -s nullglob
function have_any() {
    [ $# -gt 0 ]
}

if have_any ./*.flac; then
    echo true
fi

Die Funktions have_anyVerwendungen $#ihre Argumente zu zählen, und [ $# -gt 0 ]dann prüfen , ob es zumindest ein Argument ist. Die Verwendung von ./*.flacstatt nur *.flacim Aufruf von have_anydient dazu, Probleme zu vermeiden, die durch Dateien mit Namen wie verursacht werden --help.

jochen
quelle
1

Zur Vervollständigung mit zsh:

if [[ -n *.flac(#qN) ]]; then
  echo true
fi

Dies ist am Ende des Abschnitts Bedingte Ausdrücke im zsh-Handbuch aufgeführt. Da das [[Globbing von Dateinamen deaktiviert ist, müssen wir die Generierung von Dateinamen (#q)am Ende der Globbing-Zeichenfolge erzwingen und dann das NFlag ( NULL_GLOBOption), um zu erzwingen, dass die generierte Zeichenfolge leer ist, falls keine Übereinstimmung vorliegt.

Iso
quelle
1

Hier ist eine ziemlich einfache Lösung:

if [ "$(ls -A | grep -i \\.flac\$)" ]; then echo true; fi

Wie Sie sehen können, ist dies nur eine Codezeile, aber es funktioniert gut genug. Es sollte sowohl mit Bash als auch mit einem Posix-kompatiblen Shell-ähnlichen Dash funktionieren. Es unterscheidet auch nicht zwischen Groß- und Kleinschreibung und es ist egal, welche Art von Dateien (regulär, Symlink, Verzeichnis usw.) vorhanden sind. Dies kann hilfreich sein, wenn Sie Symlinks oder ähnliches haben.

TSJNachos117
quelle
Ich mag das, weil ls -AR eine rekursive Suche durchführt. Gut zum Durchsuchen des Inhalts von Zip-Archiven nach dem Entpacken.
Justin Cress
0

Ich habe es versucht:

if [ -f *.html ]; then
    echo "html files exist"
else
    echo "html files dont exist"
fi

Ich habe diesen Code problemlos für andere Dateien verwendet, aber für HTML-Dateien habe ich eine Fehlermeldung erhalten :

[: too many arguments

Ich habe dann die Zähllösung von @ JeremyWeir ausprobiert, die für mich funktioniert hat.

Denken Sie daran, dass Sie die Zählung zurücksetzen müssen, wenn Sie dies in einer Schleife tun:

count=$((0))
GChuf
quelle