glob 패턴에 정의된 변수를 사용한 Bash 대체

glob 패턴에 정의된 변수를 사용한 Bash 대체

다음 예에서는 이 문제를 설명합니다. FILENAME교체를 사용할 때 에코가 올바르게 인쇄되고 패턴으로 인식되는 이유는 무엇 입니까?

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

답변1

FILEPATH_WITH_GLOB="/home/user/file_*"

이제 다음 FILEPATH_WITH_GLOB을 포함합니다 ./home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAME포함하다 file_*.

echo $FILENAME                #file_1234

$FILENAME목록 컨텍스트에서 따옴표가 없으면 확장은 분할+글로브 연산자를 통해 진행되므로 일치하는 파일 목록으로 확장됩니다.파일 이름 생성에 실행매개변수 확장.

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

목록 컨텍스트에서는 여전히 따옴표가 없는 인수 확장이므로 여전히 분할+glob을 거칩니다. 하지만 여기서는 ile_*패턴이 어떤 파일과도 일치하지 않으므로 패턴 자체로 확장됩니다.

아마도 당신이 원하는 것은 다음과 같습니다:

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

또는 배열에 저장할 수도 있습니다.

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

첫 번째 일치 항목에만 관심이 있거나 일치 항목이 하나만 있다는 것을 알고 있는 경우 $files. 에는 (에서 상속된 동작 , in (fixed )) 대신 배열의 모든 요소 로 확장하는 bash일반적으로 성가신 동작이 있으므로 파일을 참조할 수 있습니다. , 그러나 여기서는 한 번만 원하는 동작입니다.$files${files[0]}kshzsh

관련 정보