Domanda Estrarre il nome file e l'estensione in Bash


Voglio ottenere il nome file (senza estensione) e l'estensione separatamente.

La soluzione migliore che ho trovato finora è:

NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`

Questo è sbagliato perché non funziona se il nome del file contiene più . personaggi. Se, diciamo, ho a.b.js, prenderà in considerazione a e b.js, invece di a.b e js.

Può essere fatto facilmente in Python con

file, ext = os.path.splitext(path)

ma preferirei non attivare un interprete Python solo per questo, se possibile.

Qualche idea migliore?


1614
2018-06-08 14:00


origine


risposte:


Innanzitutto, ottieni il nome del file senza il percorso:

filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"

In alternativa, puoi concentrarti sull'ultima "/" del percorso anziché su "." che dovrebbe funzionare anche se hai estensioni di file imprevedibili:

filename="${fullfile##*/}"

2806
2018-06-08 14:05



~% FILE="example.tar.gz"
~% echo "${FILE%%.*}"
example
~% echo "${FILE%.*}"
example.tar
~% echo "${FILE#*.}"
tar.gz
~% echo "${FILE##*.}"
gz

Per maggiori dettagli, vedi espansione del parametro shell nel manuale di Bash.


502
2018-06-08 14:05



Di solito conosci già l'estensione, quindi potresti voler usare:

basename filename .extension

per esempio:

basename /path/to/dir/filename.txt .txt

e otteniamo

filename

279
2017-10-19 10:56



Puoi usare la magia delle variabili POSIX:

bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo ${FILENAME%%.*}
somefile
bash-3.2$ echo ${FILENAME%.*}
somefile.tar

C'è un avvertimento in questo se il tuo nome file era del modulo ./somefile.tar.gz poi echo ${FILENAME%%.*} rimuoverà avidamente la partita più lunga al . e avresti la stringa vuota.

(Puoi aggirare il problema con una variabile temporanea:

FULL_FILENAME=$FILENAME
FILENAME=${FULL_FILENAME##*/}
echo ${FILENAME%%.*}

)


Questo luogo spiega di più.

${variable%pattern}
  Trim the shortest match from the end
${variable##pattern}
  Trim the longest match from the beginning
${variable%%pattern}
  Trim the longest match from the end
${variable#pattern}
  Trim the shortest match from the beginning

125
2018-02-05 09:09



Non sembra funzionare se il file non ha estensione, o nessun nome file. Ecco cosa sto usando; usa solo i builtin e gestisce più (ma non tutti) nomi di file patologici.

#!/bin/bash
for fullpath in "$@"
do
    filename="${fullpath##*/}"                      # Strip longest match of */ from start
    dir="${fullpath:0:${#fullpath} - ${#filename}}" # Substring from 0 thru pos of filename
    base="${filename%.[^.]*}"                       # Strip shortest match of . plus at least one non-dot char from end
    ext="${filename:${#base} + 1}"                  # Substring from len of base thru end
    if [[ -z "$base" && -n "$ext" ]]; then          # If we have an extension and no base, it's really the base
        base=".$ext"
        ext=""
    fi

    echo -e "$fullpath:\n\tdir  = \"$dir\"\n\tbase = \"$base\"\n\text  = \"$ext\""
done

E qui ci sono alcuni test:

$ basename-and-extension.sh / / home / me / / home / me / file /home/me/file.tar /home/me/file.tar.gz /home/me/.hidden / home / me / .hidden.tar / home / me / ...
/:
    dir = "/"
    base = ""
    ext = ""
/ Home / me /:
    dir = "/ home / me /"
    base = ""
    ext = ""
/ Home / me / file:
    dir = "/ home / me /"
    base = "file"
    ext = ""
/home/me/file.tar:
    dir = "/ home / me /"
    base = "file"
    ext = "tar"
/home/me/file.tar.gz:
    dir = "/ home / me /"
    base = "file.tar"
    ext = "gz"
/home/me/.hidden:
    dir = "/ home / me /"
    base = ".hidden"
    ext = ""
/home/me/.hidden.tar:
    dir = "/ home / me /"
    base = ".hidden"
    ext = "tar"
/ Home / me / ..:
    dir = "/ home / me /"
    base = ".."
    ext = ""
.:
    dir = ""
    base = "."
    ext = ""

65
2017-09-10 05:17



Puoi usare basename.

Esempio:

$ basename foo-bar.tar.gz .tar.gz
foo-bar

È necessario fornire basename con l'estensione che deve essere rimossa, tuttavia se si esegue sempre tar con -z allora sai che l'estensione sarà .tar.gz.

Questo dovrebbe fare ciò che vuoi:

tar -zxvf $1
cd $(basename $1 .tar.gz)

40
2018-02-05 08:50



Mellen scrive in un commento su un post del blog:

Usando Bash, c'è anche ${file%.*} per ottenere il nome del file senza estensione e ${file##*.} per ottenere l'estensione da solo. Questo è,

file="thisfile.txt"
echo "filename: ${file%.*}"
echo "extension: ${file##*.}"

Uscite:

filename: thisfile
extension: txt

24
2017-07-21 10:24