bash: hogyan adhatja vissza a fájlkiterjesztéseket?

Írni akarok egy szkriptet, amely csak a bemeneti fájlnév kiterjesztését adja vissza. Például a textfile.txt vissza kell adnia txt.

Új vagyok a Linuxban és a bash-ban, és I megpróbálja megtanulni az alapvető szkriptek írását. Köszönöm!

Megjegyzések

  • Lásd még: stackoverflow.com/questions/965053/…
  • Mi a linux-4.2.3.tar.xz fájl kiterjesztése, amelyet a kernel.org ? Mi a /bin/bash fájl kiterjesztése, amely minden bizonnyal elérhető a rendszerén? Látja, hogy a ” fájlkiterjesztés ” fogalma meglehetősen idegen a Linuxban. A pont utáni rész nagyon csekély jelentőséggel bír a rendszer számára – ez inkább a felhasználó figyelmeztetése arra, hogy mit várhat el attól a fájltól. És ez a jel hazudhat vagy téves lehet.

Válasz

A shell, például bash, sok karakterlánc-manipuláció funkciók. Az egyik lehetővé teszi, hogy mindent eltávolítson egy adott mintáig:

${VAR##GLOB} 

A fenti szintaxis mindent eltávolít az $VAR a glob GLOB első mérkőzéséig. Tehát a fájl kiterjesztésének a neve nélküli nyomtatásához tegye a következőket:

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

Ne feledje, hogy ez egynél több “kiterjesztéssel” is foglalkozhat:

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

Ha ezt nem szeretné, használjon helyette egy # -t, amely a legrövidebb egyezést távolítja el a leghosszabbak közül:

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

Ha ezt egy könyvtár összes fájlján futtatja, a következőket teheti:

$ 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 teljesség kedvéért a fájl nevét a kiterjesztés nélkül is megszerezheti a ${file%.*} használatával:

$ 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 

Megjegyzések

  • ez nem működik ‘ olyan dolgoknál, mint a foo / .git / bar / baz gondolom meg tudná csinálni az echo test.txt | -t awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
  • @PaulM mire gondolsz? Ez a ‘ sa kiterjesztés nélküli fájl, mit várhatna ettől?
  • 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. Nem látok ‘ problémát.

Válasz

paraméterbővítéssel :

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

A ${parameter##word} pattern eltávolítja a legnagyobb előtagot, amely megfelel a word -nek (minden, kivéve a fájlvéget).

Válasz

Egy nagyon egyszerű bash szkript, amely megteheti, amit akar, a következő lenne:

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

A szkript script.sh test.txt, és amit csinál,

  • a $1 fájlt kinyomtatja a stdout-ba. A $1 az első paraméter, amelyet a szkriptnek adunk, ebben az esetben test.txt.

  • a echo stdout kimenetét a stdin-hez csatolják a awk fájlhoz, amely szétválasztja a húrt ( >) a . oldalon, majd kinyomtatja a felosztás utolsó elemét (txt ebben az esetben).

Csak egy apró megjegyzés, ezt egy vonalhajózással lehet megtenni, mert elég egyszerű feladat:

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

Megjegyzések

  • Idézetet kell hozzáadnia a $1 köré, különben kockáztathatja a szóközöket tartalmazó fájlnevek megszakítását.
  • ez nem működik ‘ olyan dolgoknál, mint a foo / .git / bar / baz. Azt hiszem, meg tudná csinálni az echo test.txt-t

/ ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘

Válasz

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

Futtatás:

./script.sh index.html 

Kimenet:

index html 

További információ: Shell paraméter kibővítése | gnu.org

Válasz

Ehhez számos figyelmeztetést kell figyelembe venni:

  • A foo.d/bar fájlnak nincs kiterjesztése, ez nem egy foo fájl, amelynek .d/bar kiterjesztés.
  • azt is fontolóra veheti, hogy .bashrc nincs kiterjesztése
  • A . és a .. speciális címtárfájlokat valószínűleg speciálisan kell kezelni, és úgy kell tekinteni, hogy nincsenek kiterjesztéseik.
  • minek a kiterjesztése file.tar.gz? gz vagy tar.gz? Mi a helyzet a holiday.picture.jpg vagy a bash-4.4?
  • Mit kell adnia a foo.d/? Üres vagy d?

Itt tenném:

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

Megjegyzések

  • Kiváló válaszkezelés a szokásos figyelmeztetésekkel és a hasznos kóddal is, főleg funkcióként. / h2>

    Még néhány lehetőséget felvetek, ha sed vagy Perl telepítve van:

     #!/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 itt: sed és s/^.*?\.//&&print itt: perl: próbálja meg a legrövidebb karakterláncot helyettesíteni, nem ., amelyet egy . karakter követ a karakterlánc elején; ha a helyettesítés megtörténhet, nyomtassa ki a helyettesítés eredményét;
     % bash script.sh file.bin Extension: bin Extension: bin  

    Válasz

    Legyen óvatos. Unix / Linux (és MacOS) esetén a “fájlnévkiterjesztés” csak informatív (ha ennyi). Tökéletesen rendelkezhet egy photo.gif nevű Perl-szkriptet, vagy egy poem.txt nevű GIF-fájlt. Vagy akár egy some.txt.png nevű fájlt.

    Megjegyzések

    • Ez ‘ ugyanolyan informatív az MS Windows rendszerben, de ‘ csak annyi, hogy az alapértelmezett shell program erőteljesebb feltételezéseket tesz a kiterjesztés – tartalom párosítással kapcsolatban, és kell-e lennie egy a név és a tartalom közötti eltérés, az egész általában csak hibákat, szegényeket kezd kiabálni.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük