bash: hvordan returnerer du filtypenavne?

Jeg vil skrive et script for kun at returnere udvidelsen af inputfilnavnet. For eksempel skal textfile.txt returnere txt.

Jeg er ny til Linux og bash, og jeg “m forsøger at lære at skrive grundlæggende scripts. Tak!

Kommentarer

  • Se også stackoverflow.com/questions/965053/…
  • Hvad er udvidelsen af linux-4.2.3.tar.xz -fil, som du kan downloade fra kernel.org ? Hvad er den udvidelse af /bin/bash -fil, der helt sikkert er tilgængelig på dit system? Ser du, begrebet " filtypenavn " er ret fremmed i Linux. Delen efter prikken har meget ringe betydning for systemet – det er snarere et signal for brugeren om, hvad han kunne forvente af den fil. Og det signal kan lyve eller være forkert.

Svar

Skallen, for eksempel bash, har mange strengmanipulation -funktioner. En af dem lader dig fjerne alt op til et givet mønster:

${VAR##GLOB} 

Syntaksen ovenfor fjerner alt fra variablen $VAR indtil den første kamp på globen GLOB. Så for at udskrive en fils udvidelse uden dens navn kan du gøre:

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

Bemærk, at dette også kan håndtere mere end en “udvidelse”:

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

Hvis du ikke ønsker det, skal du bruge en # i stedet, som i stedet fjerner den korteste match af den længste:

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

For at køre dette på alle filer i en mappe kan du gø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 fuldstændighedens skyld kan du også få filnavnet uden filtypenavn ved hjælp af ${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 til ting som foo / .git / bar / baz Jeg gætter på, at du kunne lave ekko test.txt | awk -F ' / ' ' {udskriv $ NF} ' | awk -F '. ' ' {udskriv $ NF} '
  • @PaulM hvad mener du? Den ' en fil uden filtypenavn, hvad ville du forvente at få af det?
  • echo " / foo /var/.git/foo/bar.bz" | awk -F ' / ' ' {udskriv $ NF} ' | awk -F '. ' ' {udskriv $ NF} ' == > > bz
  • @PaulM file="/foo/var/.git/foo/bar.bz"; echo "${file##*.}": bz. Jeg ser ikke ' et problem.

Svar

Med parameterudvidelse :

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

${parameter##word} mønster fjerner det største præfiks, der matcher word (alt undtagen filen slutter).

Svar

Et meget simpelt bash-script, der kunne gøre, hvad du vil, ville være følgende:

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

Scriptet påberåbes som script.sh test.txt, og hvad det gør er

  • det udskriver $1 til stdout. $1 er den første parameter, der gives til scriptet, i dette tilfælde test.txt.

  • stdout-output fra echo ledes til stdin for awk som opdeler strengen (test.txt) på . og derefter udskriver det sidste element i split (txt i dette tilfælde).

Bare en lille bemærkning, dette kan gøres med en one-liner, fordi det “er en ret simpel opgave:

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

Kommentarer

  • Du skal tilføje anførselstegn omkring $1, ellers risikerer du at bryde filnavne, der indeholder mellemrum osv.
  • dette virker ikke ' for ting som foo / .git / bar / baz Jeg antager, at du kunne lave 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" 

Kør:

./script.sh index.html 

Output:

index html 

Mere info: Udvidelse af shell-parameter | gnu.org

Svar

For at gøre det er der flere advarsler, der skal tages i betragtning:

  • foo.d/bar -filen har ingen udvidelse, den er ikke en foo -fil med en .d/bar udvidelse.
  • Det kan også være en god idé at overveje, at .bashrc ikke har nogen udvidelse
  • . og .. specielle katalogfiler bør sandsynligvis behandles specielt og anses for ikke at have nogen udvidelse.
  • hvad er udvidelsen til file.tar.gz? gz eller tar.gz? Hvad med holiday.picture.jpg eller bash-4.4?
  • Hvad skal du returnere til foo.d/? Tom eller d?

Her gør jeg:

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

Kommentarer

  • Fremragende svarhåndtering også de sædvanlige advarsler og nyttig kode, især som en funktion.

Svar

Jeg vil smide nogle flere muligheder, hvis du har sed eller Perl installeret:

 #!/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 at erstatte den korteste rækkefølge af tegn, ikke . efterfulgt af et . tegn i begyndelsen af strengen; hvis udskiftningen kunne foretages, skal du udskrive resultatet af udskiftningen;
% bash script.sh file.bin Extension: bin Extension: bin

Svar

Vær forsigtig. I Unix / Linux (og MacOS) er “filtypenavnet” bare informativt (hvis så meget). Du kan perfekt have et Perl-script kaldet photo.gif eller en GIF-fil med navnet poem.txt. Eller endda en fil med navnet some.txt.png.

Kommentarer

  • Det ' er lige så informativ i MS Windows, det ' er bare, at der inde i standard shell-programmet antager stærkere antagelser om udvidelsen – parring af indhold, og skulle der være en uoverensstemmelse mellem navngivning og indhold, det hele begynder normalt bare at råbe fejl, den stakkels ting.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *