Ik wil een script schrijven om alleen de extensie van de invoerbestandsnaam te retourneren. textfile.txt
zou bijvoorbeeld txt
moeten retourneren.
Ik ben nieuw bij Linux en bash, en ik “m proberen te leren basisscripts te schrijven. Bedankt!
Reacties
Answer
De shell, bash bijvoorbeeld, heeft veel stringmanipulatie functies. Met een ervan kun je alles verwijderen tot een bepaald patroon:
${VAR##GLOB}
De bovenstaande syntaxis verwijdert alles van de variabele $VAR
tot de eerste overeenkomst van de glob GLOB
. Dus om de extensie van een bestand zonder de naam af te drukken, zou je het volgende kunnen doen:
$ file="file.txt" $ echo ${file##*.} txt
Merk op dat dit ook met meer dan één “extensie” kan omgaan:
$ file="file.new.txt" $ echo ${file##*.} txt
Als je dat niet wilt, gebruik dan een #
, die in plaats daarvan de kortste overeenkomst verwijdert of the longest:
$ echo ${file#*.} new.txt
Om dit nu op alle bestanden in een directory uit te voeren, zou je het volgende kunnen doen:
$ 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
En voor de volledigheid kunt u de bestandsnaam ook zonder de extensie krijgen met ${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
Reacties
- dit werkt niet ‘ niet voor zaken als foo / .git / bar / baz Ik denk dat je echo test.txt | zou kunnen doen awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
- @PaulM wat bedoel je? Dat ‘ sa-bestand zonder extensie, wat zou je daarvan verwachten?
- 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
. Ik ‘ zie geen probleem.
Antwoord
Met parameteruitbreiding :
$ x="textfile.txt" $ echo ${x##*.} txt
De ${parameter##word}
patroon verwijdert het grootste voorvoegsel dat overeenkomt met word
(alles behalve de bestandseinde).
Antwoord
Een heel eenvoudig bash-script dat zou kunnen doen wat je wilt, zou het volgende zijn:
#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}"
Het script wordt aangeroepen als script.sh test.txt
, en wat het doet is
-
het drukt
$1
naar stdout.$1
is de eerste parameter die aan het script wordt gegeven, in dit gevaltest.txt
. -
de standaarduitvoer van
echo
wordt doorgesluisd naar stdin voorawk
die de string splitst (test.txt
) op.
en dan wordt het laatste element van de splitsing afgedrukt (txt
in dit geval).
Gewoon een kleine opmerking, dit kan gedaan worden met een oneliner omdat het “een vrij simpele taak is:
echo test.txt | awk -F "." "{print $NF}"
Opmerkingen
- U moet aanhalingstekens plaatsen rond
$1
, anders riskeert u bestandsnamen die spaties bevatten enz. te breken. - dit werkt niet ‘ t werkt voor zaken als foo / .git / bar / baz Ik denk dat je echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘
Antwoord
#!/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"
Uitvoeren:
./script.sh index.html
Uitvoer:
index html
Meer info: Shell Parameter Expansion | gnu.org
Answer
Om dit te doen, zijn er verschillende kanttekeningen waarmee u rekening moet houden:
- Het
foo.d/bar
-bestand heeft geen extensie, het is “geenfoo
-bestand met een.d/bar
extensie. - Je kunt ook overwegen dat
.bashrc
geen extensie heeft - De
.
en..
speciale mapbestanden moeten waarschijnlijk speciaal worden behandeld en als geen enkele extensie worden beschouwd. - waarvoor is de extensie?
file.tar.gz
?gz
oftar.gz
? Hoe zit het metholiday.picture.jpg
ofbash-4.4
? - Wat moet je retourneren voor
foo.d/
? Leeg ofd
?
Hier “zou ik doen:
#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done
Opmerkingen
- Uitstekende afhandeling van antwoorden, ook de gebruikelijke kanttekeningen en nuttige code, vooral als functie.
Antwoord
Ik “zal wat meer opties toevoegen voor het geval je sed
of Perl hebt geïnstalleerd:
#!/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
insed
ens/^.*?\.//&&print
inperl
: probeer de kortste reeks tekens te vervangen, niet.
gevolgd door een.
teken aan het begin van de string; als de vervanging kon worden gemaakt, druk dan het resultaat van de vervanging af;
% bash script.sh file.bin Extension: bin Extension: bin
Antwoord
Wees voorzichtig. In Unix / Linux (en MacOS) is de “bestandsnaamextensie” slechts informatief (als dat veel is). Je kunt perfect een Perl-script hebben met de naam photo.gif
, of een GIF-bestand met de naam poem.txt
. Of zelfs een bestand met de naam some.txt.png
.
Reacties
- Het ‘ is net zo informatief in MS Windows, het ‘ is alleen dat daarin het standaard shell-programma sterkere aannames doet over de koppeling tussen extensie en inhoud, en als er een mismatch tussen naamgeving en inhoud, het hele ding begint meestal gewoon fouten te schreeuwen, het arme ding.
linux-4.2.3.tar.xz
-bestand dat u kunt downloaden van kernel.org ? Wat is de extensie van het/bin/bash
-bestand dat zeker op uw systeem beschikbaar is? Zie je, het concept van ” bestandsextensie ” is nogal vreemd in Linux. Het gedeelte na de punt heeft weinig betekenis voor het systeem – het is eerder een indicatie voor de gebruiker over wat hij van dat bestand mag verwachten. En dat signaal kan liegen of verkeerd zijn.