bash: Wie geben Sie Dateierweiterungen zurück?

ch möchte ein Skript schreiben, um nur die Erweiterung des Eingabedatennamens zurückzugeben. Zum Beispiel sollte textfile.txt txt zurückgeben.

Ich bin neu in Linux und bash und ich bin versuchen zu lernen, wie man grundlegende Skripte schreibt. Vielen Dank!

Kommentare

  • Siehe auch stackoverflow.com/questions/965053/…
  • Was ist die Erweiterung der Datei linux-4.2.3.tar.xz, die Sie von kernel.org ? Welche Erweiterung der Datei /bin/bash ist mit Sicherheit auf Ihrem System verfügbar? Sie sehen, das Konzept der “ Dateiendung “ ist unter Linux ziemlich fremd. Der Teil nach dem Punkt hat für das System nur eine sehr geringe Bedeutung – er ist eher ein Hinweis für den Benutzer, was er von dieser Datei erwarten könnte. Und dieser Hinweis kann lügen oder falsch sein.

Antwort

Die Shell, zum Beispiel bash, hat viele Zeichenfolgenmanipulation . Mit einer davon können Sie alles bis zu einem bestimmten Muster entfernen:

${VAR##GLOB} 

Die obige Syntax entfernt alles aus der Variablen $VAR bis zur ersten Übereinstimmung des Globus GLOB. Um die Dateierweiterung ohne Namen zu drucken, haben Sie folgende Möglichkeiten:

$ file="file.txt" $ echo ${file##*.} txt 

Beachten Sie, dass dies auch mehr als eine „Erweiterung“ betreffen kann:

$ file="file.new.txt" $ echo ${file##*.} txt 

Wenn Sie das nicht möchten, verwenden Sie stattdessen eine #, wodurch stattdessen die kürzeste Übereinstimmung entfernt wird der längsten:

$ echo ${file#*.} new.txt 

Um dies nun für alle Dateien in einem Verzeichnis auszuführen, können Sie Folgendes tun:

$ ls file.avi file.pdf file.png file.txt $ for file in *; do echo "$file : ${file##*.}"; done file.avi : avi file.pdf : pdf file.png : png file.txt : txt 

Der Vollständigkeit halber können Sie den Dateinamen auch ohne Erweiterung mit ${file%.*}:

Kommentare

  • Dies funktioniert ‚ nicht für Dinge wie foo / .git / bar / baz Ich denke du könntest echo test.txt | machen awk -F ‚ / ‚ ‚ {print $ NF} ‚ | awk -F ‚. ‚ ‚ {print $ NF} ‚
  • @PaulM was meinst du? Diese ‚ ist eine Datei ohne Erweiterung. Was würden Sie davon erwarten?
  • echo “ / foo /var/.git/foo/bar.bz“ | awk -F ‚ / ‚ ‚ {print $ NF} ‚ | awk -F ‚. ‚ ‚ {print $ NF} ‚ == > > bz
  • @PaulM file="/foo/var/.git/foo/bar.bz"; echo "${file##*.}": bz. Ich sehe ‚ kein Problem.

Antwort

Mit Parametererweiterung :

$ x="textfile.txt" $ echo ${x##*.} txt 

Die ${parameter##word} pattern entfernt das größte Präfix, das mit word übereinstimmt (alles außer dem Dateiende).

Antwort

Ein sehr einfaches Bash-Skript, das das tun kann, was Sie wollen, ist das Folgende:

#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}" 

Das Skript wird als script.sh test.txt und

  • gibt $1 an stdout aus. $1 ist der erste Parameter, der dem Skript zugewiesen wird, in diesem Fall test.txt.

  • Die stdout-Ausgabe von echo wird für awk an stdin weitergeleitet, wodurch die Zeichenfolge aufgeteilt wird (test.txt) auf . und druckt dann das letzte Element der Teilung (in diesem Fall txt).

Nur eine kleine Bemerkung, dies kann mit einem Einzeiler gemacht werden, da dies eine ziemlich einfache Aufgabe ist:

echo test.txt | awk -F "." "{print $NF}" 

Kommentare

  • Sie müssen Anführungszeichen um $1 hinzufügen, da sonst die Gefahr besteht, dass Dateinamen mit Leerzeichen usw. beschädigt werden.
  • dies funktioniert nicht ‚ funktioniert nicht für Dinge wie foo / .git / bar / baz. Ich denke, Sie könnten echo test.txt | awk -F ‚ / ‚ ‚ {print $ NF} ‚ | awk -F ‚.‘ ‚ {print $ NF} ‚

Antwort

#!/bin/bash my_file=`basename "$1"` # get full file name as a script parameter and strip the path my_extension="${my_file##*.}" my_file="${my_file%.*}" # will return base file name before the extension echo "$my_file" echo "$my_extension" 

Ausführen:

./script.sh index.html 

Ausgabe:

index html 

Weitere Informationen: Shell-Parametererweiterung | gnu.org

Antwort

Hierzu sind verschiedene Einschränkungen zu beachten:

  • Die Datei foo.d/bar hat keine Erweiterung, es handelt sich nicht um eine foo -Datei mit einer .d/bar -Erweiterung.
  • Sie möchten möglicherweise auch berücksichtigen, dass .bashrc keine Erweiterung
  • Die . und .. spezielle Verzeichnisdateien sollten wahrscheinlich speziell behandelt werden und keine Erweiterung haben.
  • Wofür ist die Erweiterung? file.tar.gz? gz oder tar.gz? Was ist mit holiday.picture.jpg oder bash-4.4?
  • Was sollten Sie für foo.d/? Leer oder d?

Hier würde ich Folgendes tun:

#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done 

Kommentare

  • Hervorragende Antwortbehandlung, auch die üblichen Einschränkungen und nützlichen Codes, insbesondere als Funktion.

Antwort

Ich werde einige weitere Optionen hinzufügen, falls Sie sed oder Perl installiert haben:

 #!/bin/bash ext=$(<<<"$1" sed -n "s/^[^.]*\.//p") printf "Extension: $ext\n" ext=$(<<<"$1" perl -ne "s/^.*?\.//&&print") printf "Extension: $ext\n" exit 0  
  • s/^[^.]*\.//p in sed und s/^.*?\.//&&print in perl: Versuchen Sie, die kürzeste Zeichenfolge zu ersetzen, die nicht . gefolgt von einem . -Zeichen am Anfang der Zeichenfolge; Wenn die Ersetzung vorgenommen werden konnte, drucken Sie das Ergebnis der Ersetzung aus:
 % bash script.sh file.bin Extension: bin Extension: bin  

Antwort

Seien Sie vorsichtig. Unter Unix / Linux (und MacOS) ist die „Dateinamenerweiterung“ nur informativ (wenn so viel). Sie können perfekt ein Perl-Skript mit dem Namen photo.gif oder eine GIF-Datei mit dem Namen poem.txt haben. Oder sogar eine Datei mit dem Namen some.txt.png.

Kommentare

  • Es ‚ ist in MS Windows genauso informativ, ‚ ist nur so, dass das Standard-Shell-Programm dort stärkere Annahmen über die Paarung von Erweiterung und Inhalt macht, und sollte es eine geben Nichtübereinstimmung zwischen Benennung und Inhalt, das Ganze fängt normalerweise nur an, Fehler zu schreien, das arme Ding.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.