SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor

Bash globbing 와일드카드 및 extglob 사용법

Bash 셸이 명령 실행 전 와일드카드를 파일 목록으로 확장하는 원리를 설명합니다. nullglob, dotglob, globstar 및 extglob 부정 패턴을 활용해 복잡한 파일 선택 작업을 정확하게 수행하는 방법을 예제와 함께 정리했습니다.

명령 실행 전 Bash globbing이 수행하는 작업

Bash globbing은 명령이 시작되기 전에 셸이 *.log과 같은 패턴을 실제 파일 이름의 정렬된 목록으로 변환하는 과정입니다. rm *.logrm에 패턴을 직접 전달하지 않습니다. Bash는 디렉터리를 읽고, 일치하는 이름을 유지하며, 이를 정렬한 뒤 각 이름을 별도의 인자로 하여 rm을 실행합니다. rm 프로그램은 패턴이 사용되었는지 여부를 알 수 없습니다.

globbing과 관련하여 발생하는 거의 모든 의외의 상황은 이 한 가지 사실에서 비롯됩니다. 일치 작업은 셸이 수행하며, 해당 시점에 존재하는 파일을 대상으로 합니다. 명령은 완성된 목록만을 전달받습니다. 이를 공식적으로는 경로명 확장(pathname expansion)이라고 합니다. Globbing은 일상적으로 사용하는 용어이며, 두 용어 모두 같은 의미를 나타냅니다.

연습용 작은 트리 구조 만들기

아래의 모든 예제는 동일한 파일을 대상으로 실행됩니다. 임시 디렉터리에 파일을 생성하면 중요한 데이터에 영향을 주지 않으며, 명령 한 번으로 깔끔하게 정리할 수 있습니다.

lab=$(mktemp -d)
cd "$lab"
mkdir -p logs archive/2025 archive/2026
touch app.log app.log.1 app.log.2 app.log.10 error.log debug.LOG
touch notes.txt notes.md README 'weekly report.log'
touch .env .apprc
touch logs/nginx.log logs/nginx.log.1
touch archive/2025/dec.log archive/2026/jan.log

mktemp -d은 새로운 디렉터리를 생성하고 그 경로를 반환하며, $(...)는 해당 경로를 lab 변수에 저장합니다. 이 문법이 생소하다면 명령 치환이 명령의 출력을 캡처하는 방법에서 자세한 내용을 확인할 수 있습니다.

생성된 구조를 확인하고 셸 버전을 점검하십시오. 마지막 부분의 참고 사항 하나가 버전에 따라 달라지기 때문입니다.

ls -a
bash --version

여기에 있는 모든 내용은 bash 4.0 이상에서 작동합니다. 마지막 부분의 globskipdots 참고 사항은 bash 5.2 이상에 적용되며, 이는 2026년 8월 기준 최신 Ubuntu 및 Debian 릴리스에 포함된 버전입니다.

이 문서 전반에서 사용하는 미리보기 명령은 printf '%s\n' PATTERN입니다. 이 명령은 일치하는 항목을 줄 단위로 출력하며 디스크의 내용을 변경하지 않으므로, 확신이 서지 않는 패턴에 대해서도 안전하게 실행할 수 있습니다.

세 가지 와일드카드: 별표, 물음표, 대괄호

  • *은 빈 문자열을 포함하여 임의의 문자열과 일치합니다.
  • ?는 정확히 한 문자와 일치합니다.
  • [...]은 대괄호 안에 포함된 집합 중 정확히 한 문자와 일치합니다.
printf '%s\n' *.log
printf '%s\n' app.log.?
printf '%s\n' app.log.[0-9]
printf '%s\n' notes.*
printf '%s\n' *

두 번째 줄을 생성한 파일 목록과 비교해 보십시오. ?은 오직 한 문자만 나타내므로, 두 자리 숫자로 된 접미사는 해당 패턴에 포함되지 않습니다. 이를 app.log.[0-9]*로 확장하여 다시 실행하고 차이를 확인하십시오.

세 가지 와일드카드 모두에 두 가지 규칙이 적용됩니다. 어떤 와일드카드도 /과는 일치하지 않으므로, 패턴은 하나의 디렉터리 수준 내에서만 작동합니다. 또한, 맨 앞에 오는 .는 리터럴로 입력해야 하므로, *로 시작하는 패턴은 모든 숨김 파일을 건너뜁니다. 이 두 번째 규칙 때문에 rm *은 도트 파일(dotfiles)을 건드리지 않습니다.

글로브(glob) 결과는 현재 로캘의 정렬 순서에 따라 정렬되며, 이는 문자 단위의 텍스트 정렬입니다. 따라서 10 접미사는 2 접미사보다 앞에 정렬되는데, 이는 비교 과정에서 숫자로 인식하지 않기 때문입니다. printf '%s\n' app.log.*를 실행한 다음 ls -v app.log.*을 실행하여 두 결과를 비교해 보십시오. ls -v은 포함된 숫자를 값에 따라 정렬하며, sort -V는 파이프라인에서 동일한 작업을 수행합니다.

문자 클래스와 범위

대괄호 안에는 목록, 범위 또는 부정문을 작성할 수 있습니다.

  • [ch]c 또는 h 중 하나의 문자와 일치합니다.
  • [a-f]은 a부터 f까지의 범위에 있는 하나의 문자와 일치합니다.
  • [!0-9]은 숫자가 아닌 하나의 문자와 일치합니다. [^0-9]도 같은 의미입니다.
printf '%s\n' [dn]*
printf '%s\n' *.[A-Z]*
printf '%s\n' [A-Z]*

범위는 시스템마다 다르게 동작할 수 있는 부분입니다. 범위는 일반적인 ASCII가 아닌 현재 로케일의 정렬 순서에 따라 해석되므로, 일부 시스템에서는 [a-z]가 대문자와도 일치할 수 있습니다. Bash에는 일반 ASCII 순서를 강제하는 globasciiranges 옵션이 있으며, 최신 빌드에서는 기본적으로 활성화되어 있으므로 가정하지 말고 shopt globasciiranges을 사용하여 직접 확인하십시오. 어디서나 동일하게 일치해야 하는 스크립트라면 스크립트 상단에 LC_ALL=C를 별도의 줄에 설정하여 정렬 순서를 고정할 수 있으며, 이렇게 하면 모든 범위가 일반 바이트 순서로 돌아갑니다.

해당 할당은 그 자체로 하나의 명령이어야 합니다. 접두사로 작성된 LC_ALL=C ls [a-z]*ls에 대해서만 로케일을 설정할 뿐이며, ls가 시작되기 전에 셸이 이미 자체 로케일에서 패턴을 확장해 버리기 때문입니다. 이는 첫 번째 섹션에서 다룬 규칙이 다시 나타나는 사례입니다.

중괄호 확장(Brace expansion)은 글로빙(globbing)이 아닙니다

중괄호는 와일드카드처럼 보이지만 동작 방식은 전혀 다릅니다. 중괄호 확장은 글로빙보다 훨씬 먼저 실행되며, 디스크를 전혀 참조하지 않습니다.

echo file{1,2,3}.txt
echo {01..10}
echo {a..e}
echo {0..20..5}

위 파일들은 존재하지 않지만 확장은 그대로 수행됩니다. 이것이 핵심적인 차이입니다. 글로브(glob)는 파일 시스템에 질의를 던지지만, 중괄호는 단순히 텍스트를 생성할 뿐입니다. 중괄호가 파일을 찾는 용도가 아니라 생성하는 용도로 적합한 이유가 바로 여기에 있습니다.

mkdir -p site/{css,js,img}
cp app.log{,.bak}
touch report-{2025,2026}-{01,02}.csv

cp app.log{,.bak}app.logapp.log.bak이라는 두 개의 단어로 확장됩니다. 쉼표 앞의 빈 항목이 원본 텍스트를 그대로 유지하기 때문입니다. {01..10}는 0 패딩을 유지합니다. 양쪽 끝점 중 하나라도 0으로 시작하면 bash가 생성된 모든 숫자의 너비를 동일하게 맞추기 때문입니다.

확장 순서를 이해하면 사용자가 자주 겪는 실패의 원인도 알 수 있습니다. Bash는 중괄호를 먼저 확장하고, 그다음 변수를 확장하며, 마지막으로 경로명 확장을 수행합니다.

n=5
echo {1..$n}

$n이 숫자로 변환될 시점에는 이미 중괄호 확장이 종료된 상태이므로 범위가 생성되지 않습니다. seq 1 "$n"을 사용하거나, for ((i=1; i<=n; i++))와 같이 C 스타일 루프를 작성하십시오.

패턴이 아무것도 일치하지 않을 때 발생하는 현상

이는 첫 번째 실패 유형이며, 누구나 한 번쯤 겪게 됩니다. 기본적으로 bash는 일치하지 않는 패턴을 그대로 둡니다. 단어는 입력한 그대로 명령에 전달되므로, 명령은 *, ., t, m, p 문자를 그대로 받아 파일 이름으로 처리하려고 시도합니다.

printf '%s\n' *.tmp

printf 명령에서는 별다른 문제가 없습니다. 하지만 무언가를 생성하는 명령에서는 문제가 됩니다. .tmp 파일이 없는 디렉터리에서 touch *.tmp를 실행하면 문자 그대로 *.tmp이라는 이름의 파일이 생성됩니다. 이후 이 파일을 삭제하려면 셸이 다시 확장하지 못하도록 따옴표를 사용해야 합니다: rm -- '*.tmp'.

두 가지 셸 옵션을 통해 이 규칙을 변경할 수 있습니다. 일치하는 항목이 없는 패턴에 대해 각각 시도해 보고 설정을 해제해 보십시오.

shopt -s nullglob
printf '%s\n' *.tmp
shopt -u nullglob

shopt -s failglob
printf '%s\n' *.tmp
shopt -u failglob

nullglob을 설정하면 일치하지 않는 패턴이 아무것도 없는 상태로 확장되므로, 명령은 작성한 것보다 적은 인수로 실행됩니다. 이는 루프를 사용할 때 의도하는 동작입니다. nullglob이 꺼져 있으면 for f in *.tmpf에 리터럴 패턴을 담아 본문을 한 번 실행하는데, 이는 거의 모든 스크립트에서 버그로 작용합니다. nullglob이 켜져 있으면 본문은 0번 실행됩니다.

nullglob은 그 자체로 위험 요소를 내포하고 있습니다. 모든 인수가 제거된 명령도 그대로 실행되기 때문입니다. ls *.nope은 인수가 없는 ls이 되어 전체 디렉터리 목록을 출력합니다. grep -l needle *.nopegrep -l needle이 되는데, 읽을 파일이 없으므로 표준 입력을 기다리게 되어 마치 멈춘 것처럼 보입니다. 루프에 필요한 경우에만 nullglob을 켜고, 루프가 끝나면 다시 끄십시오.

failglob은 다른 방식을 취합니다. 일치하지 않는 패턴은 오류로 간주되어 bash가 이를 보고하고, 명령은 전혀 실행되지 않습니다. 이는 대화형 셸에 적합한 설정입니다. 오타가 포함된 패턴이 rm에 리터럴 이름으로 전달되는 것을 방지하기 때문입니다.

숨김 파일: dotglob

shopt -s dotglob
printf '%s\n' *
shopt -u dotglob

해당 블록을 실행하고 앞서 확인한 일반 printf '%s\n' *과 목록을 비교하십시오. dotglob는 선행 점(dot) 규칙을 제거하므로 *는 숨김 파일 이름도 일치시킵니다. ... 항목은 dotglob 설정과 관계없이 항상 제외됩니다.

dotglob을 사용하지 않을 때 숨김 파일에 접근하는 일반적인 방법은 .*이며, 이는 과거에 위험한 방식이었습니다. bash 5.2 이전 버전에서는 .*...과도 일치했기 때문에, chmod -R 755 .*와 같은 재귀 명령을 실행하면 상위 디렉터리까지 탐색하는 문제가 있었습니다. Bash 5.2부터는 기본적으로 활성화되는 globskipdots 옵션이 추가되어 모든 확장 결과에서 ...가 제외됩니다. 구형 시스템에서는 이 옵션을 사용할 수 없으므로, 의존하기 전에 shopt globskipdots을 실행하여 확인하십시오.

globstar: 트리 전체를 탐색하는 매칭

shopt -s globstar
printf '%s\n' **/*.log
printf '%s\n' **/
shopt -u globstar

globstar가 설정되면, **은 전체 경로 구성 요소를 형성하여 모든 깊이의 파일과 디렉터리를 매칭합니다. 여기에는 0단계 깊이도 포함되므로, **/*.log는 현재 디렉터리뿐만 아니라 logs/archive/ 아래의 모든 항목을 포함합니다. 끝에 슬래시가 붙은 **/는 디렉터리만 매칭하므로, 트리 구조를 빠르게 파악하는 방법으로 유용합니다.

globstar이 설정되지 않으면, **는 일반적인 *처럼 동작하며 한 디렉터리 내에서만 머무릅니다. 옵션을 끄고 동일한 패턴을 실행하여 비교해 보십시오. 다른 곳에서 복사한 재귀 패턴이 예상보다 훨씬 적은 결과를 반환한다면, 대개 이 설정 때문입니다. globstar은 모든 bash에서 기본적으로 꺼져 있습니다.

알아두어야 할 한 가지 제한 사항이 있습니다. **은 디렉터리로 향하는 심볼릭 링크를 따라가지 않습니다. 심볼릭 링크로 연결된 트리 구조를 탐색하려면 대신 find -L을 사용해야 합니다.

nocaseglob, 대소문자를 구분하지 않는 이름 처리

shopt -s nocaseglob
printf '%s\n' *.log
shopt -u nocaseglob

nocaseglob 옵션은 파일 이름 일치 여부를 확인할 때 대소문자를 구분하지 않도록 설정하므로, 대문자 .LOG 접미사가 소문자 .log 패턴과 일치하게 됩니다. 첫 번째 섹션의 목록과 이 결과를 비교해 보십시오. 이 옵션은 셸에서 이어지는 모든 명령의 일치 규칙을 변경하여 나중에 디버깅을 어렵게 만들 수 있으므로, 사용 직후에 즉시 끄는 것이 좋습니다.

nocaseglob는 파일 이름 확장(filename expansion)에만 적용됩니다. case 문 내부나 이중 대괄호 테스트에서의 패턴 일치를 위한 관련 옵션은 nocasematch이며, 이 두 옵션은 별도로 설정해야 합니다.

extglob: "이것 제외"를 표현하는 패턴

확장 패턴은 기본적으로 꺼져 있습니다. 다음 명령을 별도의 줄에 입력하여 활성화합니다.

shopt -s extglob

다섯 가지 형식이 있으며, 각 형식은 |로 구분된 패턴 목록을 인자로 받습니다.

  • ?(list)은 0회 또는 1회 일치를 의미합니다.
  • *(list)은 0회 이상 일치를 의미합니다.
  • +(list)은 1회 이상 일치를 의미합니다.
  • @(list)는 나열된 대안 중 정확히 하나와 일치합니다.
  • !(list)은 나열된 대안 중 어느 것과도 일치하지 않는 모든 항목과 일치합니다.

확장 패턴은 해당 옵션이 이미 켜진 셸에서 읽어야 하므로, 아래 배치 코드는 bash -O extglob로 시작하는 작은 스크립트에 작성합니다. -O 플래그는 새 셸이 파일의 첫 줄을 읽기 전에 shopt 옵션을 설정하므로, 파일 내의 모든 패턴이 올바르게 해석됩니다. 이 섹션의 마지막 문단은 순서가 중요한 이유를 설명합니다.

cat > patterns.sh <<'EOF'
printf '%s\n' @(app|error).log
printf '%s\n' app.log.+([0-9])
printf '%s\n' *.@(md|txt)
printf '%s\n' !(*.log)
printf '%s\n' !(*.log|*.md|README)
EOF
bash -O extglob patterns.sh

+([0-9])은 하나 이상의 숫자를 의미하므로, 길이가 얼마든 상관없이 번호가 붙은 접미사를 모두 포함합니다. 이는 앞서 언급한 ? 제한에 대한 해결책이며, 두 패턴을 연속으로 실행하여 결과를 확인해 볼 가치가 있습니다.

부정 형식은 "무엇을 제외한 전부"를 찾는 해답이며, extglob을 활성화하는 주된 이유입니다. 이 형식과 관련하여 사람들이 흔히 놀라는 두 가지 사실이 있습니다.

이 형식은 파일뿐만 아니라 디렉터리도 일치 대상에 포함하므로, ls !(*.log)는 디렉터리 이름 대신 해당 디렉터리 내부의 내용을 나열합니다. 이름 자체를 보려면 ls -d을 사용하거나 printf 미리보기를 활용하십시오.

또한 다른 모든 glob과 마찬가지로 점(dot) 규칙을 따르므로, !(*.log).log로 끝나지 않는 모든 가시적인 이름을 포함합니다. 숨김 파일까지 포함하려면 dotglob도 함께 설정해야 합니다.

!(...)에 포함된 !은 glob 부정 연산자입니다. 이는 별도의 단계에서 실행되는 독립적인 기능인 히스토리 확장 및 뱅 문자와는 아무런 관련이 없습니다.

주의해야 할 또 다른 함정은 구문 분석 시점에 발생합니다. Bash는 명령을 실행하기 전에 전체 명령을 먼저 분석하므로, 같은 줄에서 extglob을 활성화하고 확장 패턴을 사용하면 실패합니다. 옵션이 꺼진 상태에서 패턴이 먼저 분석되기 때문입니다. shopt -s extglob은 반드시 패턴보다 앞선 별도의 줄에, 스크립트 상단 근처에 두어야 합니다. 함수 본문은 함수가 정의될 때 분석되므로, 호출 시점이 아니라 정의 시점 이전에 옵션이 켜져 있어야 합니다. 위 배치 코드처럼 bash -O extglob로 셸을 시작하면 구문 분석이 시작되기 전에 순서 문제가 해결됩니다.

셸이 패턴을 확장하며, 명령어가 확장하지 않음

이는 두 번째 실패 유형이며, 광범위한 버그의 원인을 설명합니다.

grep -l needle *.log
find . -name '*.log'
find . -name *.log

첫 번째 줄은 bash가 매칭을 수행하도록 하며, grep는 파일 이름 목록을 전달받습니다. 두 번째 줄은 패턴을 따옴표로 묶었으므로, find은 5개의 문자 *.log을 전달받아 시작 지점 아래의 모든 깊이에서 자체적으로 매칭을 수행합니다. 세 번째 줄은 버그입니다. bash가 현재 디렉터리에 대해서만 패턴을 먼저 확장하므로, find은 특정 이름 하나를 찾으라는 지시를 받게 됩니다. 일치하는 항목이 하나뿐인 디렉터리에서는 잘못된 대상을 조용히 검색합니다. 두 개 이상의 항목이 일치하면, find은 표현식이 와야 할 자리에 추가 이름들이 전달되었기 때문에 사용법 오류를 보고합니다.

규칙은 간단합니다. 패턴이 명령어를 위한 것이라면 따옴표로 묶으십시오. 셸을 위한 것이라면 그대로 두십시오. 동일한 구분 원칙이 tarrsync--exclude 패턴, 그리고 grep--include 필터에도 적용됩니다.

글로브(glob)는 문자를 공유하더라도 정규 표현식(regular expression)이 아닙니다. 글로브에서 *는 임의의 문자열을 의미합니다. 정규 표현식에서 *는 앞선 요소가 0번 이상 반복됨을 의미하므로, grep '*.log'은 겉보기와는 완전히 다른 결과를 요구하게 됩니다.

변수도 동일한 연산 순서를 따릅니다. 글로빙은 변수 확장 이후에 실행되므로, 패턴을 담고 있는 변수를 따옴표로 묶지 않으면 디렉터리 내에서 확장됩니다.

pat='*.log'
printf '%s\n' $pat
printf '%s\n' "$pat"

따옴표를 사용하지 않으면 bash는 변수의 결과에 대해 글로빙을 수행합니다. 따옴표를 사용하면 패턴은 리터럴로 유지됩니다. 이와 관련하여 의존해야 할 결과가 하나 있습니다. 글로빙으로 생성된 단어는 공백을 기준으로 다시 분할되지 않습니다. 따라서 for f in *.log은 공백이 포함된 파일 이름을 하나의 이름으로 처리하지만, for f in $(ls *.log)은 해당 이름을 두 개의 단어로 분리합니다. 글로브를 직접 반복문(loop)에 사용하십시오.

파괴적인 패턴을 실행하기 전에 미리보기

새로운 패턴을 시도할 때 rm를 첫 번째 명령어로 사용하지 마십시오. 무해한 명령어로 패턴을 먼저 실행하여 목록을 확인한 뒤, 줄 앞부분의 명령어만 변경하십시오.

target='!(*.log)'
printf '%s\n' $target
ls -ld -- $target
rm -- $target

패턴을 target에 한 번 작성하면 세 줄이 서로 어긋나는 일을 방지할 수 있습니다. $target은 bash가 확장할 수 있도록 의도적으로 따옴표를 씌우지 않습니다. printf '%s\n'는 파일명을 줄마다 하나씩 출력할 뿐 아무것도 변경하지 않습니다. ls -ld은 디렉터리 내부 내용을 나열하는 대신 항목 자체를 보여주며, 모드 열을 통해 어떤 항목이 디렉터리인지 확인할 수 있습니다. 이는 재귀적 삭제를 수행하기 전에 반드시 확인해야 할 사항입니다. drwxr-xr-x 권한 비트 읽기에서 해당 열을 다룹니다.

위쪽 화살표 키로 이전 명령어를 불러와 명령어만 수정하면 패턴을 동일하게 유지할 수 있습니다. 패턴을 기억에 의존해 다시 입력하는 과정에서 실수가 발생합니다.

패턴 앞에 --를 추가하십시오. 이는 옵션의 끝을 나타내므로, -로 시작하는 파일명도 플래그가 아닌 이름으로 처리됩니다.

스크립트의 특정 구간에서 globbing을 끄고 싶다면 set -f으로 비활성화하고 set +f로 다시 활성화하십시오.

rm은 실행 취소가 불가능하므로 이러한 습관이 중요합니다. rm -rf로 삭제된 파일 복구하기는 작업이 느리고 대개 완벽하게 복구되지 않으므로, 미리보기를 하는 것이 사고를 수습하는 것보다 훨씬 비용이 적게 듭니다.

연습용 디렉터리 작업이 끝나면 정리하십시오. 경로를 먼저 출력하여 확인하십시오. rm -rf에 잘못된 변수를 지정하는 것이 바로 이 섹션에서 경고하는 사고의 전형이기 때문입니다.

cd ~
echo "$lab"
rm -rf -- "$lab"

FAQ

find . -name *.log이 왜 잘못된 파일을 찾습니까?

bash가 find가 시작되기 전에 *.log을 확장하기 때문입니다. 셸은 현재 디렉터리에서 패턴과 일치하는 항목을 찾아 그 결과 파일명을 find에 전달하며, 이후 find은 해당 파일명 하나만 모든 깊이에서 검색하게 됩니다. 두 개 이상의 파일이 일치하면 find은 표현식이 와야 할 자리에 추가 인자를 받게 되어 사용법 오류를 보고합니다. 패턴을 find . -name '*.log'와 같이 따옴표로 묶으면 find가 자체 규칙과 재귀 탐색을 사용하여 직접 일치 항목을 찾게 됩니다.

패턴이 리터럴 텍스트로 나타나는 것은 무슨 의미입니까?

일치하는 항목이 없다는 뜻입니다. 기본적으로 bash는 일치하지 않는 패턴을 그대로 두어 원본 문자를 명령어로 전달하며, 명령어는 이를 파일명으로 처리합니다. 일치하지 않는 패턴을 오류로 간주하여 명령을 중단하려면 shopt -s failglob을 설정하고, 아무것도 확장되지 않게 하려면 shopt -s nullglob을 설정하십시오. nullglob 사용 시 인자가 없을 때도 명령이 정상적으로 동작하는지 확인해야 합니다. 인자가 없으면 ls *.nope은 빈 ls가 되어 전체 디렉터리 목록을 출력하기 때문입니다.

bash에서 특정 패턴 하나를 제외한 모든 파일을 일치시키려면 어떻게 합니까?

shopt -s extglob을 별도 줄에 입력하여 확장 패턴을 활성화한 뒤 부정 형식을 사용하십시오. !(*.log).log로 끝나지 않는 이름을 일치시키며, !(*.log|*.md)은 두 패턴을 모두 제외합니다. dotglob가 설정되지 않으면 숨김 파일은 결과에서 제외되며 디렉터리는 포함되므로, rm에 전달하기 전에 printf '%s\n' !(*.log)로 패턴을 미리 확인하십시오.

*은 왜 숨김 파일을 건너뜁니까?

앞의 점(dot)은 리터럴로 일치해야 하므로 *은 점으로 시작하는 이름을 일치시키지 못합니다. 숨김 파일에 접근하려면 .*를 사용하거나, shopt -s dotglob을 설정하여 일반 패턴에 숨김 파일을 포함시키십시오. dotglob 설정 시에도 ... 항목은 항상 제외됩니다. bash 5.2 이상에서는 기본적으로 활성화된 globskipdots 옵션을 통해 .*에서도 이 항목들을 제외합니다.

**가 작동하려면 globstar가 필요합니까?

네, 그렇습니다. shopt -s globstar이 없으면 bash는 **을 일반적인 *로 취급하여 한 디렉터리 내부만 일치시키고 멈춥니다. globstar가 켜져 있으면 전체 경로 구성 요소를 형성하는 **가 모든 깊이에서 일치하므로, **/*.log은 현재 디렉터리와 그 아래의 모든 하위 디렉터리에 도달하며, **/은 디렉터리만 일치시킵니다. **는 디렉터리로 향하는 심볼릭 링크를 따라가지 않으므로, 심볼릭 링크로 구성된 트리 구조에는 find -L을 사용하십시오.

#bash#globbing#shell#linux#scripting