bash: hvordan returnerer du filutvidelser?

Jeg vil skrive et skript for å bare returnere utvidelsen av navnet på inndatafilen. For eksempel skal textfile.txt returnere txt.

Jeg er ny til Linux og bash, og jeg «m prøver å lære å skrive grunnleggende skript. Takk!

Kommentarer

  • Se også stackoverflow.com/questions/965053/…
  • Hva er utvidelsen av linux-4.2.3.tar.xz fil som du kan laste ned fra kernel.org ? Hva er utvidelsen av /bin/bash -filen som absolutt er tilgjengelig på systemet ditt? Ser du, konseptet med " filtypen " er ganske fremmed i Linux. Delen etter punktet har veldig liten betydning for systemet – det er snarere et signal for brukeren om hva han kan forvente av den filen. Og det signalet kan lyve eller være feil.

Svar

Skallet, for eksempel bash, har mange strengmanipulering -funksjoner. En av dem lar deg fjerne alt opp til et gitt mønster:

${VAR##GLOB} 

Syntaksen ovenfor fjerner alt fra variabelen $VAR til første kamp på globen GLOB. Så for å skrive ut filtypen uten navn, kan du gjøre:

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

Merk at dette også kan håndtere mer enn en «utvidelse»:

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

Hvis du ikke vil ha det, bruk en # i stedet, som i stedet fjerner den korteste kampen av den lengste:

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

Nå, for å kjøre dette på alle filer i en katalog, kan du gjøre:

$ 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 

Og for fullstendighets skyld kan du også få filnavnet uten filtypen ved å bruke ${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 

Kommentarer

  • dette fungerer ikke ' t fungerer for ting som foo / .git / bar / baz Jeg antar at du kan gjøre ekko test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} '
  • @PaulM hva mener du? Den ' en fil uten utvidelse, hva forventer du å få av det?
  • 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. Jeg ser ikke ' et problem.

Svar

Med parameterutvidelse :

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

${parameter##word} mønster fjerner det største prefikset som samsvarer med word (alt unntatt filen slutter).

Svar

Et veldig enkelt bash-skript som kan gjøre det du vil, er følgende:

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

Skriptet påkalles som script.sh test.txt, og hva den gjør er

  • den skriver ut $1 til stdout. $1 er den første parameteren som er gitt til skriptet, i dette tilfellet test.txt.

  • stdout-utgangen til echo ledes til stdin for awk som deler strengen (test.txt) på . og deretter skriver den ut det siste elementet i splittelsen (txt i dette tilfellet).

Bare en liten kommentar, dette kan gjøres med en en-liner fordi det er en ganske enkel oppgave:

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

Kommentarer

  • Du må legge til anførselstegn rundt $1, ellers risikerer du å bryte filnavn som inneholder mellomrom osv.
  • dette fungerer ikke ' for ting som foo / .git / bar / baz Jeg antar at du kan gjøre ekko test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '.' ' {print $ NF} '

Svar

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

Kjør:

./script.sh index.html 

Utgang:

index html 

Mer info: Skalparameterutvidelse | gnu.org

Svar

For å gjøre det, er det flere advarsler å ta hensyn til:

  • foo.d/bar -filen har ingen utvidelse, den er ikke en foo -fil med en .d/bar utvidelse.
  • Det kan også være lurt å vurdere at .bashrc ikke har noen utvidelse
  • . og .. spesielle katalogfiler bør sannsynligvis behandles spesielt og anses å ikke ha noen utvidelse.
  • hva er utvidelsen for file.tar.gz? gz eller tar.gz? Hva med holiday.picture.jpg eller bash-4.4?
  • Hva skal du returnere for foo.d/? Tom eller d?

Her gjør jeg:

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

Kommentarer

  • Utmerket svarhåndtering også vanlige advarsler og nyttig kode, spesielt som en funksjon.

Svar

Jeg vil ha noen flere alternativer i tilfelle du har sed eller Perl installert:

 #!/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 i sed og s/^.*?\.//&&print i perl: prøv å erstatte den korteste tegnrekkefølgen, ikke . etterfulgt av et . tegn i begynnelsen av strengen; hvis det kunne skiftes ut, skriv ut resultatet av erstatningen;
 % bash script.sh file.bin Extension: bin Extension: bin  

Svar

Vær forsiktig. I Unix / Linux (og MacOS) er «filnavnet» bare informativt (hvis så mye). Du kan perfekt ha et Perl-skript kalt photo.gif, eller en GIF-fil som heter poem.txt. Eller til og med en fil som heter some.txt.png.

Kommentarer

  • Den ' er like informativt i MS Windows, det ' er bare det at standard shell-programmet gir sterkere antagelser om utvidelsen – innholdsparring, og skulle det være en uoverensstemmelse mellom navngivning og innhold, det hele begynner vanligvis bare å rope feil, det stakkars.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *