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
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
$1til stdout.$1er den første parameter, der gives til scriptet, i dette tilfældetest.txt. -
stdout-output fra
echoledes til stdin forawksom opdeler strengen (test.txt) på.og derefter udskriver det sidste element i split (txti 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 enfoo-fil med en.d/barudvidelse. - Det kan også være en god idé at overveje, at
.bashrcikke 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?gzellertar.gz? Hvad medholiday.picture.jpgellerbash-4.4? - Hvad skal du returnere til
foo.d/? Tom ellerd?
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/^[^.]*\.//pisedogs/^.*?\.//&&printiperl: 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.
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.