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
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 tilfellettest.txt
. -
stdout-utgangen til
echo
ledes til stdin forawk
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 enfoo
-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
ellertar.gz
? Hva medholiday.picture.jpg
ellerbash-4.4
? - Hva skal du returnere for
foo.d/
? Tom ellerd
?
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
ised
ogs/^.*?\.//&&print
iperl
: 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.
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.