다음 예제와 같이 변수에 지정된 파일을 나열할 수 있어야 합니다.
X="myfile.txt"
$ ls ${X}
불행히도 일부 사람들은 파일 이름에 공백을 사용하므로 다음과 같은 경우가 될 수 있습니다.
X="my file.txt"
다음 방법으로 해결 가능합니다ls "${X}"
그러나 다음과 같은 경우에도 이런 일이 발생할 수 있습니다.
X="my file.*"
와일드카드는 큰따옴표 내에서 확장되지 않기 때문에 문제가 발생합니다.
모든 상황에 적용되는 것이 있나요?
편집하다
X
다음과 같은 배열로 선언됩니다 .
X=("my file."*)
ls "$X[@]"
선언할 때 와일드카드 문자를 확장하므로 충분하지 않습니다. 사용할 때 확장해야 합니다 ls
.
답변1
세게 때리다
에서는 bash
변수를 인용 해제하는 것을 분할+글로브 연산자라고 부르기도 합니다.
분할 부분은 $IFS
특수 매개변수를 사용하여 조정할 수 있으며, 전역 부분은 noglob
다음 옵션을 사용하여 조정할 수 있습니다.
와일드카드의 경우에만 $IFS
빈 문자열로 설정합니다.
file_pattern='foo bar *.txt'
IFS= # disable splitting
set +o noglob # make sure glob is enabled
ls -ld -- $file_pattern # split+glog with split disabled.
패턴이 어떤 파일과도 일치하지 않으면 ls
리터럴 인수를 받고 foo bar *.txt
파일이 존재하지 않는다고 불평합니다.
분할에 대해서만( $PATH
여기서는 콜론으로 구분된 변수 분할이 예제로 사용됨) noglob
옵션을 설정합니다.
IFS=: # split on :
set -o noglob
ls -ld -- $PATH # split+glob with glob disabled
비어 있거나 설정되지 않은 경우 $var
, 비어 있더라도 확장 시 인수가 생성되지 않고 빈 인수가 생성됩니다 $IFS
.
$PATH
비어 있음 $PATH
( unset 아님 $PATH
)은 명령이 현재 작업 디렉터리에서 검색되고 ls
인수가 전달되지 않을 때 현재 작업 디렉터리도 나열된다는 의미 이기 때문에 여기서는 허용됩니다 .
$PATH
현재 작업 디렉터리를 의미하는 (예: ) 에 빈 요소가 있는 경우 이에 대해 불평하는 /bin::/usr/bin
해당 빈 인수가 전달됩니다 . ls
한 가지 예외는 빈 요소가 마지막 요소인 경우( 에서와 같이 /bin:/usr/bin:
) 마지막 요소가 삭제된다는 것입니다.
유사한 변수를 분할하는 더 올바른 방법은 다음을 $PATH
사용하는 것입니다.
IFS=:
set -o noglob
printf '<%s>\n' $PATH''
이 추가 부분은 ''
뒤에 오는 빈 요소가 제거되는 것을 방지하고 빈 요소가 $PATH
전혀 요소가 아닌 빈 요소로 분할되도록 보장합니다.
다루기 힘든
zsh에서는 인수 확장 중에 분할 및 와일드카드가 암시적으로 수행되지 않습니다. $=var
- $IFS
분할, ${(s[separator])var}
구분 기호 기반 분할, $~var
와일드카드(또는 -분할과 와일드카드 $=~var
결합 ) $IFS
를 사용하여 명시적으로 요청 해야 합니다.
그래서:
file_pattern='foo bar *.txt'
ls -ld -- $~file_pattern
(패턴이 어떤 파일과도 일치하지 않으면 명령이 ls
중단됩니다²).
IFS=:
ls -ld -- $=PATH # preserves all empty elements even trailing ones
ls -ld -- ${(s[:])PATH} # split, discarding empty elements
ls -ld -- "${(@s[:])PATH}" # split, preserving empty elements
¹ 이 옵션을 활성화하지 않는 한(관리형이 아닌 다른 옵션 세트에서 failglob
) bash는 중단됩니다(하위 쉘을 종료하거나 하위 쉘에서 실행되지 않는 경우 읽은 모든 코드를 건너뜁니다). 또는 이 옵션을 활성화하면 다음으로 확장됩니다. 이 경우에는 아무것도 없으므로 현재 작업 디렉터리가 나열됩니다.shopt
set
nullglob
shopt
ls
² zsh에서 실패한 glob은 구문 오류처럼 처리되며 해당 쉘 프로세스는 오류 및 실패한 종료 상태로 종료됩니다(대화형 쉘에서는 기본 쉘을 종료하지 않고 프롬프트로 돌아갑니다). 여기서는 외부 명령과 마찬가지로 ls
이를 실행하기 위해 생성된 하위 프로세스만 종료됩니다. 전역 확장이 여기서 발생하기 때문입니다. ls
예를 들어 쉘 함수로 다시 정의하면 상황이 달라집니다.
답변2
와일드카드를 사용하려는 경우 변수를 사용하는 것은 여러 파일과 일치할 수 있으므로 좋은 생각이 아닙니다.
해결책: 배열을 사용하세요!
X=("my file."*)
ls "${X[@]}"
# or
for f in "${X[@]}"; do
some_command "$f"
done
값을 할당할 때는 *
따옴표 밖에 있어야 합니다.
확인하다여기변수 확장시에만 전역 확장을 위한 솔루션입니다.