Globs (Glob Patterns) 문법 정리

Globs (Glob Patterns) 문법 정리

이번 포스팅에서는 Glob Patterns, 흔히 줄여서 Globs라고 불리는 패턴 매칭에 대해서 알아보도록 하겠습니다.

Globs(Glob Patterns)란?

Globs은 오래전부터 리눅스 운영체제에서 한 번에 여러 개의 파일을 찾을 때 사용해온 패턴 매칭 기법인데요. 많은 리눅스 명령어가 인자로 Glob 패턴을 받기 때문에 알게 모르게 많이 사용하고 있으실 거에요. 예를 들어, 터미널에서 ls src/*.java와 유사한 커맨드를 날려보신 적이 있으시면 이미 어느 정도 Globs 문법을 자연스럽게 체득하셨다고 볼 수 있을 것 같습니다.

Glob 패턴 매칭은 현재 리눅스 뿐만 아니라 Shell, Java, Python, NodeJS, Go, Ruby, PHP 등 대부분의 프로그래밍 언어에서 지원하고 있는데요. 특히, 운영 체제와 프로그래밍 언어를 가리지 않고 프레임워크나 라이브러리를 설정할 때 광범위하게 사용되고 있습니다. 주로 설정 내용을 프로젝트 내의 일부 파일에만 적용하고 싶을 때 Globs가 사용되는데요. 대표적인 사례로, Git에서 코드 저장소(repository) 내에 일부 파일을 추적하지 않기 위해서 사용하는 .gitignore 파일을 들 수 있겠습니다.

또한 개발자들이 거의 매일 사용하는 코드 편집기에서도 Globs가 사용되는 것을 쉽게 볼 수 있는데요. 예를 들어, VSCode에서 파일 검색할 때, 검색 범위에 일부 파일을 포함하거나 제외시킬 수 있는 기능이 있는데 이 때도 Globs 문법으로 패턴을 입력하도록 되어있습니다. (관련 매뉴얼)

그럼 지금부터 Globs에서 어떤 와일드카드(wildcard, 특수 기호/괄호)를 제공하고 어떻게 활용하는지에 대해서 함께 살펴볼까요?

? 기호

Glob 패턴에서 ? 기호는 문자의 종류와 상관없이 정확히 한 글자와 매칭이되는데요. 예를 들어 a?라는 패턴으로는 ab, ac, ad 등과 같은 이름의 파일을 찾을 수 있습니다. 하지만 abcabab 등과 같은 이름을 가진 파일은 찾을 수 없을 것입니다.

? 기호는 연달아 사용할 수도 있는데요. 예를 들어, data/ma??.txt라는 패턴으로는 data/main.txt, data/math.txt, data/mail.txt 등과 같은 이름의 파일을 찾을 수 있을 것입니다. 하지만 data/map.txtdata/maple.txt 등과 같은 이름을 가진 찾아지지 않겠죠?

? 기호는 아무래도 매칭 범위가 짧다보니 그렇게 자주 사용되는 편은 아닙니다. 하나의 패턴으로 최대한 많은 파일을 찾는 것이 Globs의 주 용도이기 때문입니다.

* 기호

아마 Globs에서 가장 많이 사용되는 와일드카드는 * 기호는 일텐데요. * 기호는 길이와 상관없이 어떤 문자열과도 부합합니다. 심지어 공백까지도요. (공백은 길이가 0인 문자열이라고 생각하면 쉽습니다.) 단, 예외가 있는데 디렉토리 구분자로 사용되는 특수 기호, 즉 리눅스 계열에서는 /, 윈도우즈 계열에서는 \과는 부합하지 않습니다.

예를 들어, a*라는 패턴으로는 a, ab, abc, abc.txt, abc.mp3 등과 같이 이름이 a로 시작하는 모든 파일을 찾을 수 있습니다.

또 다른 예로, img라는 폴더 안에서 파일 이름은 abc로 동일한데 확장자만 다른 파일을 찾고 싶다면 img/abc.*라는 패턴을 사용하면 됩니다. 그러면 img/abc.jpg, img/abc.png, img/abc.gif와 같은 파일들이 검색될 것입니다.

** 기호

다음으로 Globs의 꽃이라고도 볼 수 있는 ** 기호에 대해서 알아볼까요? ** 기호는 0개 이상의 하위 디렉토리와 매칭이 되는데요. 예를 들어, logs/**/error.log이라는 패턴을 통해 logs/error.log, logs/a/error.log, logs/a/b/error.log, logs/a/b/c/error.log 등의 파일을 모두 찾을 수 있습니다.

특히 **/로 시작하는 패턴은 현재 디렉토리 뿐만 아니라 하위 디렉토리에 있는 파일까지 모두 재귀적으로 탐색할 수 있어서 매우 많이 쓰이는데요. 예를 들어, 현재 디렉토리 하위에 존재하는 모든 CSS 파일을 찾고 싶다면 **/*.css라는 패턴을 사용하면 됩니다. 반면에 *.css 패턴은 현재 디렉토리에 있는 CSS 파일만 찾고, 하위 디렉토리까지는 뒤지지 않습니다.

참고로 편의를 위해서 일부 설정 파일이나 개발 도구에서는 패턴 맨 앞의 **/ 기호를 생략해도 무방한 경우가 있는데요. 아무래도 파일을 검색할 때, 현재 디렉토리만 검색하기 보다는 하위에 있는 모든 디렉토리를 검색하고 싶은 경우가 많이 때문일 것입니다.

{} 괄호

리눅스에서는 파일 이름의 대소문자를 구분하기 때문에 어떤 확장자를 가진 파일을 찾을 때 소문자로 한 번 찾고 대문자로 한 번 더 찾아야하는 일이 발생하는데요. 예를 들어, 현재 디렉토리 내에 파일 이름이 jpg로 끝나거나, JPG로 끝나는 파일을 검색하고 싶을 때는 어떻게 할까요?

지금까지 배운 와일드카드를 활용해보면 **/*.jpg 패턴과 **/*.JPG 패턴을 이용해서 두 번 검색 후에 검색 결과를 합친 후 중복되는 파일을 제거해줘야 할 것입니다.

하지만 {} 괄호를 활용하면 **/*.{jpg,JPG} 패턴 하나로 통합을 할 수가 있습니다. 즉, {} 괄호는 동시에 여러 문자열을 매칭하는 것이 가능하게합니다.

또 다른 예로, HTML 문서의 확장자는 htmhtml이 둘 다 사용되는데요. 만약에 public 폴더에 있는 모든 HTML 파일을 검색하고 싶다면 public/**/*.{htm,html} 패턴을 사용할 수 있을 것입니다.

[] 괄호

간혹가다가 문자의 범위를 기준으로 파일 이름을 매칭하고 싶을 때가 있는데요. 이럴 때는 []괄호를 사용할 수 있습니다. 예를 들어, 이름에 모음 소문자를 포함하는 파일을 검색하고 싶다면 **/*[aeiou]*이라는 패턴을 사용할 수 있습니다.

- 기호를 두 문자 사이에 넣으면 두 문자 사이에 있는 모든 문자가 매칭에 사용됩니다. 예를 들어, 대문자로 이름이 시작하는 파일을 검색하고 싶다면 **/[A-Z]*이라는 패턴을 사용할 수 있습니다.

! 기호를 [] 괄호 맨 앞에 붙이면 그 뒤에 나오는 문자를 매칭에서 제외합니다. 예를 들어, **/[!A-Z]* 패턴은 대문자로 이름이 시작하지 않는 파일만을 검색해줍니다.

() 괄호

?, * 바로 뒤에 () 괄호를 사용하면 와일드카드 매칭 시 어느 정도 선택지를 제한해줄 수 있습니다.

예를 들어, ?(ab|cd)라는 패턴은 ab 또는 cd와 매칭되며 빈문자열과도 매칭됩니다. 반면에 *(ab|cd)라는 패턴은 ab, abab, cd, cdcd, abcd, cdab, ababcdabcd 등 다양한 문자열과 매칭될 수 있습니다.

따라서 파일 이름에서 있어도 되고 없어도 되는 부분을 매칭할 때 유용하게 사용할 수 있는데요.

예를 들어, React 프로젝트에서는 확장자가 .js.jsx인 파일이 공존하기 마련인데요. 이 두 개의 확장자를 쓰고 있는 모든 파일을 찾고 싶다면 **/*.js?(x)라는 패턴을 사용할 수 있습니다. 물론 살짝 패턴이 더 길어지지만 위에서 배운 {} 괄호를 사용해서 **/*.{js,jsx}를 사용해도 무방하겠죠?

Globs vs. Regex

많은 분들이 정규식(Regex, Regular Expression)을 Globs(Global Patterns)랑 혼동하시는데요. 이 둘은 얼핏 보면 비슷해보이지만 사실 알고 보면 문법이 미묘하게 틀려서 각별히 주의가 필요합니다. 예를 들어, * 기호는 Globs에서는 길이와 상관없이 모든 문자열과 매칭되지만, 정규식에서는 .*이라고 해줘야지 같은 효력이 발생합니다.

무엇보다 두 가지 패턴 매칭 방법은 용도가 크게 다릅니다. Globs는 파일 시스템을 검색하는데 특화되어 있는 반면에, 정규식은 좀 더 범용적으로 사용할 수 있는 매칭 방법입니다. 따라서 정규식은 Globs보다 더 강력한 문자열 매칭을 제공하며 문법도 훨씬 더 복잡합니다.

단순히 파일을 찾을 때는 Globs를 쓰시는 것이 훨씬 더 쉽고 실수할 확률도 그만큼 적을 것입니다.

마치며

지금까지 Globs 문법에 대해서 한 번 정리를 해보았는데 어떠셨나요? 생각보다 그렇게 많이 복잡하지는 않죠? (적어도 정규식 보다는 훨씬 간단하게 느껴지실 것입니다 😁)

자주 사용되는 Glob 패턴은 인터넷에서 검색하면 어렵지 않게 구해서 그대로 복사해서 붙여넣기할 수 있기 때문에 실무에서 직접 Glob 패턴을 짤 일을 많지 않을 수도 있습니다. 하지만 개발자로서 Glob 패턴을 일고 어떤 파일이 검색될지 스스로 파악할 수 있다면 업무에 작은 도움이 될 수 있지 않을까요? Glob 패턴이 파일 이름을 기준으로 매칭한다면, 파일 내용을 기준으로 검색할 때는 grep 명령어가 제격입니다.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord