Vreau să scriu un script pentru a returna doar extensia numelui fișierului de intrare. De exemplu, textfile.txt
ar trebui să returneze txt
.
Sunt „nou în Linux și bash și eu” m încercând să învăț cum să scriem scripturi de bază. Mulțumesc!
Comentarii
Răspuns
Coaja, de exemplu bash, are multe manipulare șiruri caracteristici. Unul dintre ele vă permite să eliminați totul până la un model dat:
${VAR##GLOB}
Sintaxa de mai sus elimină totul din variabila $VAR
până la primul meci al globului GLOB
. Deci, pentru a imprima extensia unui fișier fără numele său, puteți face:
$ file="file.txt" $ echo ${file##*.} txt
Rețineți că aceasta poate fi tratată și cu mai multe „extensii”:
$ file="file.new.txt" $ echo ${file##*.} txt
Dacă nu doriți asta, utilizați în schimb unul #
, care va elimina în schimb cea mai scurtă potrivire dintre cele mai lungi:
$ echo ${file#*.} new.txt
Acum, pentru a rula acest lucru pe toate fișierele dintr-un director, puteți face:
$ 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
Și, din motive de completitudine, puteți obține și numele fișierului fără extensia acestuia folosind ${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
Comentarii
- acest lucru nu funcționează ‘ pentru lucruri precum foo / .git / bar / baz Cred că ai putea face eco test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
- @PaulM ce vrei să spui? Acel ‘ fișier fără extensie, ce te-ai aștepta să obții din acesta?
- 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
. Nu ‘ nu văd o problemă.
Răspuns
$ x="textfile.txt" $ echo ${x##*.} txt
${parameter##word}
elimină cel mai mare prefix care se potrivește cu word
(totul, cu excepția finalizării fișierului).
Răspuns
Un script bash foarte simplu care ar putea face ceea ce doriți ar fi următorul:
#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}"
Scriptul este invocat ca script.sh test.txt
, iar ceea ce face este
-
tipărește
$1
pe stdout.$1
este primul parametru dat scriptului, în acest caztest.txt
. -
ieșirea stdout a
echo
este canalizată către stdin pentruawk
care împarte șirul (test.txt
) pe.
și apoi imprimă ultimul element al divizării (txt
în acest caz).
Doar o mică remarcă, acest lucru se poate face cu un singur liner, deoarece este „o sarcină destul de simplă:
echo test.txt | awk -F "." "{print $NF}"
Comentarii
- Trebuie să adăugați ghilimele în jurul
$1
sau riscați să spargeți numele fișierelor care conțin spații etc. - acest lucru nu ‘ funcționează pentru lucruri precum foo / .git / bar / baz Cred că ai putea face echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘
Răspuns
#!/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"
Executare:
./script.sh index.html
Ieșire:
index html
Mai multe informații: Extindere parametri Shell | gnu.org
Răspuns
Pentru a face acest lucru, există mai multe avertismente de luat în considerare:
- Fișierul
foo.d/bar
nu are extensie, nu este un fișierfoo
cu un.d/bar
extensie. - poate doriți să considerați că
.bashrc
nu are nicio extensie - și
..
ar trebui tratate special și considerate că nu au nicio extensie. - pentru ce este extensia
file.tar.gz
?gz
sautar.gz
? Ce se întâmplă cuholiday.picture.jpg
saubash-4.4
? - Ce ar trebui să returnați pentru
foo.d/
? Gol saud
?
Aici, aș face:
#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done
Comentarii
- Răspunsuri excelente care gestionează de asemenea avertismentele obișnuite și codul util mai ales ca funcție.
Răspuns
Voi mai arunca câteva opțiuni în cazul în care aveți sed
sau Perl instalat:
#!/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
însed
șis/^.*?\.//&&print
înperl
: încercați să înlocuiți cea mai scurtă secvență de caractere, nu.
urmat de un caracter.
la începutul șirului; dacă s-ar putea face substituția, tipăriți rezultatul substituției;
% bash script.sh file.bin Extension: bin Extension: bin
Răspuns
Fii atent. În Unix / Linux (și MacOS) „extensia numelui de fișier” este doar informativă (dacă este atât de mult). Puteți avea perfect un script Perl numit photo.gif
sau un fișier GIF numit poem.txt
. Sau chiar un fișier numit some.txt.png
.
Comentarii
- Acesta ‘ este la fel de informativ în MS Windows, ‘ este doar că programul shell implicit face presupuneri mai puternice cu privire la asocierea extensie – conținut și ar trebui să existe o nepotrivire între denumire și conținut, de obicei, totul începe să strige erori, săracul.
linux-4.2.3.tar.xz
pe care îl puteți descărca din kernel.org ? Care este extensia fișierului/bin/bash
care este cu siguranță disponibil în sistemul dvs.? Vedeți, conceptul de ” extensie de fișier ” este destul de străin în Linux. Partea după punct are o semnificație foarte mică pentru sistem – este mai degrabă un indiciu pentru utilizator cu privire la ceea ce s-ar putea aștepta de la acel fișier. Și acest indiciu poate minți sau poate fi greșit.