더 나은 대안.

더 나은 대안.

와일드카드와 중괄호 안에 지정된 확장 모음이 포함된 문자열을 확장하려고 합니다. 아래 예에서 설명한 것처럼 아무 것도 작동하지 않는 것 같습니다. 변수는 firstList잘 확장되지만 , secondList또는 thirdList둘 다 fourthList제대로 확장되지 않습니다. 나는 또한 다양한 버전을 시도했지만 eval아무것도 작동하지 않습니다. 어떤 도움이라도 주시면 감사하겠습니다.

#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls  $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList 
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList  
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"

답변1

그만큼껍데기따옴표가 없는 경우에만 확장되며 *, 인용하면 셸에 의한 확장이 중지됩니다.

또한 셸에서 확장하려면 중괄호 확장을 인용 해제해야 합니다.

이 작업(Echo를 사용하여 쉘이 수행하는 작업을 확인):

$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

다른 이름을 가진 파일이 있더라도:

$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1  a.ext2  b.ext1  b.ext2  c.ext3  c.ext4  d.ext3  d.ext4  none

$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

그게 왜 효과가 있나요?

그것이 왜 작동하는지 이해하는 것이 중요합니다. 확장 순서 때문이다. 먼저 "Brace 확장"과 나중에(마지막 확장) "Pathname Expansion"(일명 glob-expansion)입니다.

Brace --> Parameter (variable) --> Pathname

잠시 동안 "경로 이름 확장"을 끌 수 있습니다:

$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2

"경로 이름 확장"은 *.ext1및 의 두 가지 인수를 받습니다 *.ext2.

$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2

문제는 중괄호 확장에 변수를 사용할 수 없다는 것입니다.
이전에도 여러번 설명했지만"Brace Expansion" 내부의 변수 사용

"가변 확장"의 결과인 "보조 확장"을 확장하려면 를 사용하여 명령줄을 셸에 다시 제출해야 합니다 eval.

$ list={ext1,ext2}
$ eval echo '*.'"$list"

버팀대 -->변하기 쉬운--> 글로브 || -->중괄호--> 변수 -->글로브
........ 여기에 인용 -->^^^^^^ || 평가 ^^^^^^^^^^^^^^^^^^^^^^^^^^^

파일 이름 값은 평가 실행에 문제를 일으키지 않습니다.

$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2

그러나 의 가치는 $list안전하지 않을 수 있습니다. 그러나 값은 $list스크립트 작성자가 설정합니다. 스크립트 작성자는 다음을 제어합니다 eval. 에 대해 외부에서 설정된 값을 사용하지 마세요 $list. 이 시도:

#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"

더 나은 대안.

평가가 없는 대안은 다음과 같습니다.Bash "확장 패턴" 사용:

#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list

참고: 두 가지 솔루션(평가 및 패턴)(작성된 대로)은 공백이나 새 줄이 있는 파일 이름에 안전하다는 점에 유의하세요. 그러나 따옴표가 없거나 평가에서 따옴표를 제거하기 $list때문에 공백이 있는 경우에는 실패합니다 .$list

답변2

고려하다:

secondList='*.{ext1,ext2}'
ls $secondList 

문제는버팀대 확장수행~ 전에 변수 확장. 이는 위의 경우 중괄호 확장이 수행되지 않음을 의미합니다.

이는 bash가 명령줄을 처음 볼 때 중괄호가 없기 때문입니다. 확장한 후에 secondList는 너무 늦습니다.

다음이 작동합니다:

$ s='*'
$ ls $s.{ext1,ext2}
a.ext1  a.ext2  b.ext1  b.ext2

여기서 명령줄에는 중괄호가 있으므로버팀대 확장첫 번째 단계로 수행할 수 있습니다. 그 후, 의 값이 $s(변수 확장) 그리고 마지막으로경로명 확장수행됩니다.

선적 서류 비치

man bash확장 순서를 설명합니다.

확장 순서는 다음과 같습니다: 중괄호 확장; 물결표 확장, 매개변수 및 변수 확장, 산술 확장 및 명령 대체(왼쪽에서 오른쪽으로 수행됨) 단어 분리; 및 경로 이름 확장.

관련 정보