staging.inyokaproject.org

In einem Script ermitteln, ob ein übergebener Dateiname eine bestimmte Endung hat

Status: Gelöst | Ubuntu-Version: Server 18.04 (Bionic Beaver)
Antworten |

frechdachs

Anmeldungsdatum:
3. Juni 2013

Beiträge: 120

Hallo zusammen,

an ein Bash-Script wird ein Dateiname übergeben, z.B. irgendwas.pdf. In dem Script wird der übergebene Dateiname in der Variablen dateiname gespeichert:

1
dateiname=$1

Nun möchte ich prüfen, ob dieser Dateiname die Endung ".pdf" hat. Das mache ich zur Zeit so:

1
2
3
4
if [ $(echo "$dateiname" | grep -i -E "\.pdf$") ]
then
     echo "Dies ist eine PDF-Datei"
fi

Grundsätzlich funktioniert das problemlos. Kann man das auch eleganterer umsetzen? Gibt es "schönere" Wege?

Vielen Dank und liebe Grüße, frechdachs

Bearbeitet von rklm:

Syntaxhighlighting. Du bist lange genug dabei, bitte achte drauf.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Mit grep ginge das noch kürzer:

1
grep -qi "\.pdf$" <<< "$dateiname" && echo "Dies ist eine PDF-Datei"

Ansonsten kann man den Vergleich auch mit der Bash machen, z.B. erst den Dateinamen nach lower-case bringen und dann auf ein .pdf am Ende matchen:

1
[[ "${dateiname,,}" =~ \.pdf$ ]] && echo "Dies ist eine PDF-Datei"

frechdachs

(Themenstarter)

Anmeldungsdatum:
3. Juni 2013

Beiträge: 120

Hallo seahawk1986,

vielen Dank für die schnelle Antwort.

Ich werde mit Deinen Vorschlägen mal experimentieren...

Liebe Grüße,

frechdachs

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Es geht noch einfacher, ohne externen Prozess (damit schneller) und POSIX-kompatibel (also in der sh):

1
2
3
if [ -z "${dateiname##*.pdf}" ]; then
  echo "Dies ist eine PDF-Datei"
fi

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Noch eine Option - ebenfalls POSIX-kompatibel:

1
2
3
case "$dateiname" in
  *.pdf) echo "Dies ist eine PDF-Datei";;
esac

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Das verhält sich aber anders als das, was frechdachs in seiner Lösung gezeigt hat - die erste Variante ist immer case-sensitiv, die zweite auch, wenn man zuvor nicht shopt -s nocasematch setzt, was nicht mehr POSIX-konform wäre.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Statt den Dateinamen zu prüfen kann man auch das System, namentlich file, prüfen lassen, ob es innen wie ein PDF aussieht:

1
test  -z $(file sample.go | grep -o PDF) && echo "Ups, kein PDF" || echo "riecht nach PDF" 

Hat den Vorteil, dass es sicherer ist und mit (wohl nur selten zu erwartenden Dateiendungsabweichungen) fertig wird, den Nachteil dass es länger dauert.

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

rklm schrieb:

Es geht noch einfacher, ohne externen Prozess (damit schneller) und POSIX-kompatibel (also in der sh):

1
2
3
if [ -z "${dateiname##*.pdf}" ]; then
  echo "Dies ist eine PDF-Datei"
fi

Ich spiele gerade mit euren Lösungen rum. Diese hier funktioniert auch mit nicht-gesetzter dateiname-Variable und funktioniert nur mit exaktem pdf (Groß-/Kleinschreibung, case-sensitive). Kann man das noch ohne Subshell verbessern?

Und wieso nutzt man nicht generell file für sowas (Ja, mit subshell)?

1
2
3
4
5
6
7
8
9
#!/bin/bash
FileType=$(file -b "$1")
echo "FileType:$FileType"
echo "Substring:${FileType:0:3}"

if [ "$?" -eq 0 ] && [ ${FileType:0:3} == "PDF" ]
then
        echo Ist PDF.
fi

Edit: Der Unbekannte war schneller ☺

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

seahawk1986 schrieb:

Das verhält sich aber anders als das, was frechdachs in seiner Lösung gezeigt hat - die erste Variante ist immer case-sensitiv, die zweite auch, wenn man zuvor nicht shopt -s nocasematch setzt, was nicht mehr POSIX-konform wäre.

OK, -i hatte ich übersehen. Aber dann testet man einfach auch gegen ".PDF". Kein großes Ding. Gemischte Schreibung kommt ja eher nicht vor.

1
2
3
case "$dateiname" in
  *.pdf|*.PDF) echo "Dies ist eine PDF-Datei";;
esac

Wenn man den Mime-Type prüfen will, dann würde ich das so machen:

1
2
3
if [ "$(file -b --mime-type "$dateiname" )" = application/pdf ]; then
  echo "Dies ist eine PDF-Datei"
fi

Das handelt auch gleich den Fall ab, dass $dateiname gar nicht existiert.

user_unknown schrieb:

Statt den Dateinamen zu prüfen kann man auch das System, namentlich file, prüfen lassen, ob es innen wie ein PDF aussieht:

Gute Idee!

1
test  -z $(file sample.go | grep -o PDF) && echo "Ups, kein PDF" || echo "riecht nach PDF" 

Warum nutzt Du da -z und die Ausgabe von grep anstatt gleich den Exit-Code von grep?

1
file sample.go | fgrep -q PDF && echo "riecht nach PDF" || echo "Ups, kein PDF"

Hat den Vorteil, dass es sicherer ist und mit (wohl nur selten zu erwartenden Dateiendungsabweichungen) fertig wird, den Nachteil dass es länger dauert.

Jo.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

rklm schrieb:

OK, -i hatte ich übersehen. Aber dann testet man einfach auch gegen ".PDF". Kein großes Ding. Gemischte Schreibung kommt ja eher nicht vor.

1
2
3
case "$dateiname" in
  *.pdf|*.PDF) echo "Dies ist eine PDF-Datei";;
esac

Andererseits ist:

1
case "${dateiname,,}" in   *.pdf) echo "Dies ist eine PDF-Datei";; esac

auch kein großes Ding

1
test  -z $(file sample.go | grep -o PDF) && echo "Ups, kein PDF" || echo "riecht nach PDF" 

Warum nutzt Du da -z und die Ausgabe von grep anstatt gleich den Exit-Code von grep?

1
file sample.go | fgrep -q PDF && echo "riecht nach PDF" || echo "Ups, kein PDF"

Das wär zu kurz und elegant. 😉 Schätze ich habe was falsch gemacht, und es hat nicht auf Anhieb geklappt, und dann bin ich auf eine inferiore Lösung ausgewichen.

Hat den Vorteil, dass es sicherer ist und mit (wohl nur selten zu erwartenden Dateiendungsabweichungen) fertig wird, den Nachteil dass es länger dauert.

Jo.

Macht sich aber wohl erst ab 1000 PDFs bemerkbar.

Antworten |