bash: jak vracíte přípony souborů?

Chci napsat skript, který vrátí pouze příponu názvu vstupního souboru. Například textfile.txt by měl vrátit txt.

Jsem nový v Linuxu a bash a já snaží se naučit psát základní skripty. Děkujeme!

Komentáře

  • Viz také stackoverflow.com/questions/965053/…
  • Jaká je přípona linux-4.2.3.tar.xz souboru, který si můžete stáhnout z kernel.org ? Jaké je rozšíření souboru /bin/bash, které je ve vašem systému s největší pravděpodobností k dispozici? Vidíte, koncept " přípony souboru " je v Linuxu docela cizí. Část za tečkou má pro systém velmi malý význam – je to spíše vodítko pro uživatele, co by od tohoto souboru mohl očekávat. A tato narážka může lhát nebo být špatná.

Odpověď

Shell, například bash, má mnoho manipulace s řetězci . Jeden z nich vám umožní odstranit vše až do daného vzoru:

${VAR##GLOB} 

Výše uvedená syntaxe odstraní vše z proměnné $VAR do první shody glob GLOB. Chcete-li tedy vytisknout příponu souboru bez jeho názvu, můžete to udělat:

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

Upozorňujeme, že toto může také pracovat s více než jednou „příponou“:

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

Pokud to nechcete, použijte místo toho jednu #, která místo toho odstraní nejkratší shodu z nejdelších:

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

Chcete-li to spustit na všech souborech v adresáři, můžete udělat:

$ 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 

A pro úplnost můžete také získat název souboru bez jeho přípony pomocí ${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 

Komentáře

  • toto ' nefunguje pro věci jako foo / .git / bar / baz Myslím, že byste mohli udělat echo test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} '
  • @PaulM, co tím myslíš? Tento ' sa soubor bez přípony, co byste od toho očekávali?
  • 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. ' nevidím problém.

Odpovědět

S rozšířením parametrů :

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

${parameter##word} odstraní největší předponu, která odpovídá word (vše kromě konce souboru).

Odpovědět

Velmi jednoduchý bash skript, který umí dělat to, co chcete, bude následující:

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

Skript je vyvolán jako script.sh test.txt a to, co dělá, je

  • vytiskne $1 na standardní výstup. $1 je první parametr daný skriptu, v tomto případě test.txt.

  • standardní výstup echo je směrován na stdin pro awk, který rozděluje řetězec (test.txt) na . a poté vytiskne poslední prvek rozdělení (v tomto případě txt).

Jen malá poznámka, lze to provést jednorázovou linkou, protože je to docela jednoduchý úkol:

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

Komentáře

  • Musíte přidat uvozovky kolem $1, jinak riskujete rozbití názvů souborů, které obsahují mezery atd.
  • this does not ' t work for things like foo / .git / bar / baz I guess you could do echo test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '.' ' {print $ NF} '

Odpověď

#!/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" 

Spustit:

./script.sh index.html 

Výstup:

index html 

Další informace: Rozšíření parametrů shellu | gnu.org

Odpověď

K tomu je třeba vzít v úvahu několik upozornění:

  • Soubor foo.d/bar nemá příponu, nejedná se o soubor foo s .d/bar rozšíření.
  • můžete také zvážit, že .bashrc nemá žádné rozšíření
  • . a .. speciální adresářové soubory by pravděpodobně měly být ošetřeny speciálně a neměly by mít žádnou příponu.
  • k čemu je přípona file.tar.gz? gz nebo tar.gz? A co holiday.picture.jpg nebo bash-4.4?
  • Co byste měli za foo.d/? Prázdné nebo d?

Tady udělám:

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

Komentáře

  • Vynikající zpracování odpovědí i obvyklých upozornění a užitečného kódu, zejména jako funkce.

Odpověď

Hodím další možnosti, pokud máte sed nebo Perl nainstalován:

 #!/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 v sed a s/^.*?\.//&&print v perl: zkuste nahradit nejkratší posloupnost znaků ne . následovaný znakem . na začátku řetězce; pokud lze provést náhradu, vytiskněte si výsledek náhrady;
 % bash script.sh file.bin Extension: bin Extension: bin  

Odpověď

Buďte opatrní. V systémech Unix / Linux (a MacOS) je „přípona názvu souboru“ pouze informativní (je-li tolik). Můžete mít perfektně skript Perl s názvem photo.gif nebo soubor GIF s názvem poem.txt. Nebo dokonce soubor s názvem some.txt.png.

Komentáře

  • It ' s stejně informativní v MS Windows, ' s pouze tím, že tam výchozí shell program vytváří silnější předpoklady o párování rozšíření – obsahu, a pokud by existoval nesoulad mezi pojmenováním a obsahem, celá věc obvykle začíná křičet chyby, chudák.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *