Substitusi Bash dengan variabel yang ditentukan dari pola glob

10

Contoh di bawah ini menjelaskan masalah ini. Mengapa FILENAMEdicetak dengan benar ketika digemakan dan dianggap sebagai pola saat menggunakan substitusi?

#!/bin/bash

FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME                #file_1234
echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1
TheMeaningfulEngineer
sumber

Jawaban:

15
FILEPATH_WITH_GLOB="/home/user/file_*"

Sekarang, FILEPATH_WITH_GLOBberisi/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEberisi file_*.

echo $FILENAME                #file_1234

$FILENAMEtidak dikutip dalam konteks daftar, bahwa ekspansi mengalami split + glob operator, jadi itu diperluas ke daftar file yang cocok: pembuatan nama file dilakukan pada ekspansi parameter .

echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

Ini masih merupakan perluasan parameter yang tidak dikutip dalam konteks daftar, jadi masih mengalami split + glob. Namun di sini, ile_*polanya tidak cocok dengan file apa pun, jadi pola itu berkembang sendiri.

Apa yang mungkin Anda inginkan di sini adalah:

shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching 
                         # files in $1, $2...
for file do  # loop over them
  filename=$(basename -- "$file")
  printf '%s\n' "$filename" "${filename:1:5}"
done

Atau Anda dapat menyimpannya dalam sebuah array:

shopt -s nullglob
files=(/home/user/file_*)

Jika Anda hanya peduli pada pertandingan pertama, atau Anda tahu hanya ada satu pertandingan, Anda dapat merujuk ke file tersebut sebagai $files. bashmemiliki perilaku yang biasanya menjengkelkan yang $filesmeluas ke ${files[0]}semua elemen array (perilaku yang diwarisi dari ksh, diperbaiki zsh), tetapi di sini, itu akan menjadi perilaku yang diinginkan untuk sekali.

Stéphane Chazelas
sumber
Terima kasih untuk penjelasannya. Berhasil melakukan penyelesaian FILEPATH_WITH_GLOB=`echo /home/user/file_*` setelah penjelasan Anda.
TheMeaningfulEngineer
@Lan, itu cara yang salah untuk mengatasinya. Anda ingin menggunakan array di sini. Entah parameter posisi seperti dalam contoh saya ($ 1, $ 2 ...) atau basharray seperti: files=(/home/user/file_*).
Stéphane Chazelas
(dan semua variabel huruf besar harus benar-benar dicadangkan untuk variabel lingkungan, echotidak boleh digunakan untuk data arbitrer , variabel tidak boleh ditinggalkan tanda kutip dalam konteks daftar).
Stéphane Chazelas