Pertanyaan Ekstrak nama file dan ekstensi di Bash


Saya ingin mendapatkan nama file (tanpa ekstensi) dan ekstensi secara terpisah.

Solusi terbaik yang saya temukan sejauh ini adalah:

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

Ini salah karena tidak berfungsi jika nama file mengandung banyak . karakter. Jika, katakan saja, saya punya a.b.js, itu akan dipertimbangkan a dan b.js, dari pada a.b dan js.

Ini dapat dengan mudah dilakukan dengan Python

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

tapi saya lebih memilih untuk tidak mengaktifkan penerjemah Python hanya untuk ini, jika memungkinkan.

Ada ide yang lebih baik?


1614
2018-06-08 14:00


asal


Jawaban:


Pertama, dapatkan nama file tanpa path:

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

Alternatifnya, Anda dapat fokus pada '/' jalur terakhir alih-alih '.' yang seharusnya berfungsi bahkan jika Anda memiliki ekstensi file yang tidak dapat diprediksi:

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

Untuk lebih jelasnya, lihat ekspansi parameter shell di manual Bash.


502
2018-06-08 14:05



Biasanya Anda sudah mengetahui ekstensi, jadi Anda mungkin ingin menggunakan:

basename filename .extension

sebagai contoh:

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

dan kami dapatkan

filename

279
2017-10-19 10:56



Anda dapat menggunakan keajaiban variabel POSIX:

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

Ada peringatan bahwa jika nama file Anda adalah bentuk ./somefile.tar.gz kemudian echo ${FILENAME%%.*} akan dengan rakus menghapus pertandingan terpanjang ke . dan Anda akan memiliki string kosong.

(Anda dapat mengatasinya dengan variabel sementara:

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

)


Ini situs menjelaskan lebih lanjut.

${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



Itu tampaknya tidak berfungsi jika file tidak memiliki ekstensi, atau tidak ada nama file. Inilah yang saya gunakan; ia hanya menggunakan builtins dan menangani lebih banyak (tetapi tidak semua) nama file patologis.

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

Dan ini beberapa testcase:

$ 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



Kamu dapat memakai basename.

Contoh:

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

Anda perlu menyediakan nama dasar dengan ekstensi yang harus dihapus, namun jika Anda selalu mengeksekusi tar dengan -z maka Anda tahu ekstensi itu akan terjadi .tar.gz.

Ini harus melakukan apa yang Anda inginkan:

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

40
2018-02-05 08:50



Mellen menulis dalam komentar di sebuah posting blog:

Menggunakan Bash, ada juga ${file%.*} untuk mendapatkan nama file tanpa ekstensi dan ${file##*.} untuk mendapatkan ekstensi sendiri. Itu adalah,

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

Hasil:

filename: thisfile
extension: txt

24
2017-07-21 10:24