bash: cum returnezi extensiile de fișiere?

Vreau să scriu un script pentru a returna doar extensia numelui fișierului de intrare. De exemplu, textfile.txt ar trebui să returneze txt.

Sunt „nou în Linux și bash și eu” m încercând să învăț cum să scriem scripturi de bază. Mulțumesc!

Comentarii

  • Vezi și stackoverflow.com/questions/965053/…
  • Care este extensia fișierului linux-4.2.3.tar.xz pe care îl puteți descărca din kernel.org ? Care este extensia fișierului /bin/bash care este cu siguranță disponibil în sistemul dvs.? Vedeți, conceptul de ” extensie de fișier ” este destul de străin în Linux. Partea după punct are o semnificație foarte mică pentru sistem – este mai degrabă un indiciu pentru utilizator cu privire la ceea ce s-ar putea aștepta de la acel fișier. Și acest indiciu poate minți sau poate fi greșit.

Răspuns

Coaja, de exemplu bash, are multe manipulare șiruri caracteristici. Unul dintre ele vă permite să eliminați totul până la un model dat:

${VAR##GLOB} 

Sintaxa de mai sus elimină totul din variabila $VAR până la primul meci al globului GLOB. Deci, pentru a imprima extensia unui fișier fără numele său, puteți face:

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

Rețineți că aceasta poate fi tratată și cu mai multe „extensii”:

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

Dacă nu doriți asta, utilizați în schimb unul #, care va elimina în schimb cea mai scurtă potrivire dintre cele mai lungi:

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

Acum, pentru a rula acest lucru pe toate fișierele dintr-un director, puteți face:

$ 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 

Și, din motive de completitudine, puteți obține și numele fișierului fără extensia acestuia folosind ${file%.*}:

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

Comentarii

  • acest lucru nu funcționează ‘ pentru lucruri precum foo / .git / bar / baz Cred că ai putea face eco test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
  • @PaulM ce vrei să spui? Acel ‘ fișier fără extensie, ce te-ai aștepta să obții din acesta?
  • 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. Nu ‘ nu văd o problemă.

Răspuns

Cu extinderea parametrilor :

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

${parameter##word} elimină cel mai mare prefix care se potrivește cu word (totul, cu excepția finalizării fișierului).

Răspuns

Un script bash foarte simplu care ar putea face ceea ce doriți ar fi următorul:

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

Scriptul este invocat ca script.sh test.txt, iar ceea ce face este

  • tipărește $1 pe stdout. $1 este primul parametru dat scriptului, în acest caz test.txt.

  • ieșirea stdout a echo este canalizată către stdin pentru awk care împarte șirul (test.txt) pe . și apoi imprimă ultimul element al divizării (txt în acest caz).

Doar o mică remarcă, acest lucru se poate face cu un singur liner, deoarece este „o sarcină destul de simplă:

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

Comentarii

  • Trebuie să adăugați ghilimele în jurul $1 sau riscați să spargeți numele fișierelor care conțin spații etc.
  • acest lucru nu ‘ funcționează pentru lucruri precum foo / .git / bar / baz Cred că ai putea face echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘

Răspuns

#!/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" 

Executare:

./script.sh index.html 

Ieșire:

index html 

Mai multe informații: Extindere parametri Shell | gnu.org

Răspuns

Pentru a face acest lucru, există mai multe avertismente de luat în considerare:

  • Fișierul foo.d/bar nu are extensie, nu este un fișier foo cu un .d/bar extensie.
  • poate doriți să considerați că .bashrc nu are nicio extensie
  • și .. ar trebui tratate special și considerate că nu au nicio extensie.
  • pentru ce este extensia file.tar.gz? gz sau tar.gz? Ce se întâmplă cu holiday.picture.jpg sau bash-4.4?
  • Ce ar trebui să returnați pentru foo.d/? Gol sau d?

Aici, aș face:

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

Comentarii

  • Răspunsuri excelente care gestionează de asemenea avertismentele obișnuite și codul util mai ales ca funcție.

Răspuns

Voi mai arunca câteva opțiuni în cazul în care aveți sed sau Perl instalat:

 #!/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 în sed și s/^.*?\.//&&print în perl: încercați să înlocuiți cea mai scurtă secvență de caractere, nu . urmat de un caracter . la începutul șirului; dacă s-ar putea face substituția, tipăriți rezultatul substituției;
 % bash script.sh file.bin Extension: bin Extension: bin  

Răspuns

Fii atent. În Unix / Linux (și MacOS) „extensia numelui de fișier” este doar informativă (dacă este atât de mult). Puteți avea perfect un script Perl numit photo.gif sau un fișier GIF numit poem.txt. Sau chiar un fișier numit some.txt.png.

Comentarii

  • Acesta ‘ este la fel de informativ în MS Windows, ‘ este doar că programul shell implicit face presupuneri mai puternice cu privire la asocierea extensie – conținut și ar trebui să existe o nepotrivire între denumire și conținut, de obicei, totul începe să strige erori, săracul.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *