bash: hur returnerar du filtillägg?

Jag vill skriva ett skript för att bara returnera tillägget till inmatningsfilnamnet. Till exempel ska textfile.txt returnera txt.

Jag är ny till Linux och bash och jag ”m försöker lära sig att skriva grundläggande manus. Tack!

Kommentarer

  • Se även stackoverflow.com/questions/965053/…
  • Vad är förlängningen av linux-4.2.3.tar.xz -fil som du kan ladda ner från kernel.org ? Vad är förlängningen av /bin/bash -filen som säkert finns på ditt system? Du förstår att begreppet " filtillägg " är ganska främmande i Linux. Delen efter punkten har väldigt liten betydelse för systemet – det är snarare en ledtråd för användaren om vad han kan förvänta sig av den filen. Och den ledtråden kan ljuga eller vara fel.

Svar

Skalet, till exempel bash, har många funktioner för strängmanipulation . En av dem låter dig ta bort allt upp till ett visst mönster:

${VAR##GLOB} 

Syntaxen ovan tar bort allt från variabeln $VAR tills globens första match GLOB. Så för att skriva ut ett filtillägg utan dess namn kan du göra:

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

Observera att detta också kan hantera mer än ett ”tillägg”:

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

Om du inte vill ha det, använd en # istället för att ta bort den kortaste matchen istället av den längsta:

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

För att köra detta på alla filer i en katalog kan du göra:

$ 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 

Och för fullständighetens skull kan du också få filnamnet utan dess tillägg med ${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

  • det fungerar inte ' för saker som foo / .git / bar / baz Jag antar att du kan göra echo test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} '
  • @PaulM vad menar du? Den ' en fil utan tillägg, vad kan du förvänta dig att få från 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. Jag ser inte ' ett problem.

Svar

Med parameterutvidgning :

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

${parameter##word} mönster tar bort det största prefixet som matchar word (allt utom filen som slutar).

Svar

Ett mycket enkelt bash-skript som kan göra vad du vill skulle vara följande:

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

Skriptet anropas som script.sh test.txt, och vad det gör är

  • det skriver ut $1 till stdout. $1 är den första parametern som ges till skriptet, i detta fall test.txt.

  • stdout-utgången för echo skickas till stdin för awk som delar upp strängen (test.txt) på . och sedan skrivs det sista elementet i delningen ut (txt i detta fall).

Bara en liten anmärkning, detta kan göras med en enfodrad eftersom det är en ganska enkel uppgift:

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

Kommentarer

  • Du måste lägga till citat runt $1, annars riskerar du att bryta filnamn som innehåller mellanslag etc.
  • det fungerar inte ' för saker som foo / .git / bar / baz Jag antar att du kan göra echo 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 

Mer info: Expansion av skalparameter | gnu.org

Svar

För att göra det finns det flera försiktighetsåtgärder att ta hänsyn till:

  • foo.d/bar -filen har inget tillägg, den är inte en foo -fil med en .d/bar förlängning.
  • Du kanske också vill överväga att .bashrc inte har något tillägg
  • . och .. specialkatalogfiler bör antagligen behandlas speciellt och anses inte ha något tillägg.
  • vad är tillägget för file.tar.gz? gz eller tar.gz? Vad sägs om holiday.picture.jpg eller bash-4.4?
  • Vad ska du returnera för foo.d/? Tom eller d?

Här skulle jag göra:

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

Kommentarer

  • Utmärkt svarhantering också vanliga försiktighetsåtgärder och användbar kod särskilt som en funktion.

Svar

Jag kastar in några fler alternativ om du har sed eller Perl installerad:

 #!/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 och s/^.*?\.//&&print i perl: försök att ersätta den kortaste sekvensen med tecken inte . följt av ett . -tecken i början av strängen; om utbytet kunde göras, skriv ut resultatet av utbytet;
 % bash script.sh file.bin Extension: bin Extension: bin  

Svar

Var försiktig. I Unix / Linux (och MacOS) är ”filnamnstillägget” bara informativt (om så mycket). Du kan perfekt ha ett Perl-skript som heter photo.gif eller en GIF-fil med namnet poem.txt. Eller till och med en fil som heter some.txt.png.

Kommentarer

  • Det ' är lika informativt i MS Windows, det ' är bara att det finns standardskalprogrammet starkare antaganden om tillägget – innehållsparning, och om det skulle finnas en oöverensstämmelse mellan namngivning och innehåll, det hela börjar vanligtvis bara ropa fel, det dåliga.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *