맥 터미널에서 zsh: no matches found 가 뜰 때: pip install 'requests[security]' 따옴표가 필요한 이유와 따옴표를 안 쓰면 조용히 틀리는 경우When zsh says no matches found in the Mac terminal: why pip install 'requests[security]' needs quotes, and the cases where leaving them out goes quietly wrong
zsh 에서 no matches found 를 만난 독자가 pip 가 아니라 셸이 멈췄다는 것을 알고, 따옴표·역슬래시·noglob·nonomatch 중 자기 상황에 맞는 해결을 고르게 돕는다.
시험에서 빈 폴더의 zsh 는 대괄호·별표·물음표가 든 단어가 맞는 파일이 없으면 명령을 실행하지 않고 종료 코드 1 로 멈췄고 bash 와 sh 는 글자 그대로 넘겼다. 같은 단어에 우연히 맞는 파일이 있으면 두 셸 모두 오류 없이 그 파일 이름으로 바꿔 넘겼고, null_glob 은 인자를 통째로 지웠다. 따옴표는 파일 유무와 상관없이 글자를 그대로 넘겼다.
오류가 나면 먼저 명령에서 [ ] * ? 가 든 단어를 찾아 작은따옴표로 감싸 다시 실행하고, 같은 패턴을 자주 쓰면 따옴표 습관을 들여라. ~/.zshrc 의 전역 설정은 null_glob 이 인자를 지우고 nonomatch 도 우연히 맞는 파일을 못 막으니 따옴표를 대신하지 못한다.
목차
한 줄 요약:
zsh: no matches found는 pip 가 아니라 zsh 가[ ]·*·?를 파일 이름 패턴으로 풀다 맞는 파일이 없어 멈춘 것이니, 그 단어를 작은따옴표로 감싸 다시 치면 된다.
$ pip install requests[security]
zsh: no matches found: requests[security]
(대화형 셸에서 친 모양이다. 아래 시험은 -c 로 돌려서 오류 문구 앞에 zsh:1: 이 붙는다.)
설치 안내문에 적힌 명령을 그대로 붙여 넣었는데 이렇게 나오면 패키지가 없다는 말처럼 읽힌다. 아니다. 이 글은 같은 명령을 zsh 5.9 와 bash 3.2.57 에 나란히 넣어, 무엇이 멈췄는지, 따옴표를 안 쓰면 어떤 때 오류도 없이 틀리는지, 해결 네 가지가 어떻게 다른지 확인한 결과다. macOS 26.6.2(arm64)에서 절마다 임시 폴더를 새로 만들고(한 절 안에서는 파일을 만들었다 지우기도 했다), 사용자 설정 파일을 읽지 않게 zsh -f·bash --noprofile --norc 로 시험 전체를 두 번 돌렸는데 출력이 같았다(2026-11-10). 명령이 받은 인자를 그대로 찍어 주는 작은 스크립트(args)를 pip 대신 써서 셸이 넘긴 값만 봤다.
용어 먼저. 글롭(glob) 은 *(아무 글자 여러 개), ?(아무 글자 하나), [abc](괄호 안 글자 중 하나) 로 파일 이름을 한꺼번에 가리키는 패턴이다. 명령이 실행되기 전에 셸이 이 패턴을 실제 파일 이름 목록으로 바꿔 놓는다. requests[security] 의 [security] 는 “s, e, c, u, r, i, t, y 중 한 글자” 라는 패턴이라서, 셸 눈에는 pip 의 선택 설치 항목(extras) 표기가 아니라 requests 로 시작해 한 글자가 더 붙은 파일 이름이다.
빈 폴더에서 zsh 는 명령을 실행하지 않고 멈춘다
| 셸 | args requests[security] 를 파일이 없는 폴더에서 |
종료 코드 |
|---|---|---|
| zsh 5.9 | zsh:1: no matches found: requests[security], 명령 실행 안 됨 |
1 |
| bash 3.2.57 | 인자 하나 requests[security] 를 그대로 받음 |
0 |
| /bin/sh | bash 와 같음 | 0 |
여기서 오류 문구를 만든 쪽은 명령이 아니라 셸이다. zsh 문서의 NOMATCH 항목은 파일 이름 패턴에 맞는 파일이 없으면 “인자 목록에 그대로 두는 대신 오류를 낸다” 고 적고(맥에 설치된 man zshoptions 도 같다), 이 옵션이 zsh 에서 기본으로 켜져 있다. bash 는 반대로 맞는 게 없으면 패턴을 그대로 둔다. 이 글의 해석은, 그래서 bash 를 쓰던 사람이 맥 기본 셸이 zsh 로 바뀐 뒤 같은 설치 명령에서 이 오류를 만나기 쉽다는 것이다. 같은 오류를 묻는 Stack Overflow 질문이 requests[security]·dask[complete]·pydantic[email] 별로 여럿 보이고(검색 결과 제목만 확인했고 본문은 열지 못했다), Simon Willison 의 2020년 4월 글도 macOS Catalina 에서 pip install -e .[test] 가 zsh: no matches found: .[test] 로 막히는 것을 다룬다. 그 글은 요약으로만 확인했고, 처방은 따옴표나 noglob 이다.
*.txt 나 rm *.bak 도 같다. 빈 폴더에서 zsh 는 zsh:1: no matches found: *.txt(종료 코드 1), zsh:1: no matches found: *.bak 로 둘 다 멈췄고, bash 는 args 에는 *.txt 글자를 그대로 넘기고 rm 은 rm: *.bak: No such file or directory(종료 코드 1)를 냈다. 어느 쪽이든 지워진 것은 없다.
따옴표를 안 쓰고도 되는 날이 더 위험하다
이번에는 같은 폴더에 requestss 라는 파일 하나를 만들어 두고 같은 명령을 쳤다.
| 셸 | args requests[security] |
종료 코드 |
|---|---|---|
| zsh 5.9 | 인자 하나 requestss |
0 |
| bash 3.2.57 | 인자 하나 requestss |
0 |
[security] 패턴이 requestss(requests 뒤에 s)에 맞았고, 두 셸 모두 오류 없이 그 이름으로 바꿔 넘겼다. 실제 pip 로 오프라인(--no-index) 시험을 해도 같았다. 따옴표를 쓰면 pip 가 requests[security] 를 요구사항으로 읽어 그 항목의 의존 패키지를 따라가며 from requests[security] 가 적힌 줄(Requirement already satisfied: … 로 시작하는 줄)이 4개 찍혔고(오류 줄 0개), 폴더가 비어 있는 bash 에서도 4개였다. 반면 requestss 파일이 있는 폴더에서는 zsh 와 bash 모두 이렇게 나왔다.
ERROR: Could not find a version that satisfies the requirement requestss (from versions: none)
ERROR: No matching distribution found for requestss
이 오류는 requestss 라는 패키지를 못 찾았다는 말이라서, 원인이 따옴표라는 단서가 문구에 전혀 없다. 폴더에 우연히 맞는 파일이 있으면 “명령이 이상하게 동작한다” 로만 보이고, 그 폴더를 벗어나면 증상이 no matches found 로 바뀐다. 같은 명령이 폴더에 따라 다르게 동작한다면 따옴표부터 의심하면 된다.
find -name *.py 는 오류 없이 반만 찾는다
흔한 실수의 하나는 find . -name *.py 다. 폴더에 a.py, 하위 폴더 sub/b.py 가 있을 때 결과다.
| 명령 | 출력 |
|---|---|
find . -name *.py (zsh, bash 같음) |
./a.py 만 |
find . -name '*.py' |
./a.py, ./sub/b.py |
따옴표가 없으면 셸이 현재 폴더의 a.py 만으로 *.py 를 풀어 find . -name a.py 를 만들어 버려서 하위 폴더의 b.py 가 빠졌는데도 오류도 경고도 없다. 현재 폴더에 a.py, b.py 가 둘 있었다면 find . -name a.py b.py 가 되어 find: b.py: unknown primary or operator(종료 코드 1)로 멈췄다. 이 사고는 zsh 가 아니라 bash 에서도 똑같이 난다.
URL 의 ? 와 & 는 따로 문제를 만든다
? 도 글롭이고 & 는 앞 명령을 백그라운드로 보내는 문자다. args http://example.test/p?id=1&lang=ko 를 빈 폴더에서 쳤더니 zsh 는 zsh:1: no matches found: http://example.test/p?id=1 만 말했다. 오류가 & 앞부분까지만 적히는 것이 단서다. bash 는 ? 를 그대로 두어 args 가 http://example.test/p?id=1 까지만 받았다(& 뒤의 lang=ko 는 따로 실행되는 변수 지정이 됐다). 주소 전체를 작은따옴표로 감싸면 &lang=ko 까지 한 인자로 들어갔다.
해결 네 가지와 각각의 함정
zsh, 빈 폴더, 같은 args requests[security] 로 시험했다.
| 방법 | 쓰는 모양 | 빈 폴더 | requestss 파일이 있을 때 |
|---|---|---|---|
| 작은따옴표 | args 'requests[security]' |
글자 그대로 | 글자 그대로 |
| 역슬래시 | args requests\[security\] |
글자 그대로 | (시험 안 함) |
| noglob | noglob args requests[security] |
글자 그대로 | (시험 안 함) |
| nonomatch | setopt nonomatch; args requests[security] |
글자 그대로 | requestss 로 바뀜 |
시험한 범위에서 파일이 있든 없든 같은 값을 확인한 것은 따옴표뿐이다(역슬래시와 noglob 은 파일이 있을 때를 시험하지 않았다). nonomatch 는 “맞는 파일이 없을 때만” bash 처럼 글자를 그대로 넘기는 설정이라 위의 조용한 오동작을 막지 못한다. 그래서 ~/.zshrc 에 setopt nonomatch 를 넣어 두면 오류는 사라지지만 폴더에 따라 결과가 바뀌는 위험은 그대로다(이 글에서는 .zshrc 파일 자체는 시험하지 않고 setopt 를 명령 안에서 쳤다). noglob 은 zsh 전용 앞붙이라 이 한 명령에만 적용된다.
setopt null_glob 은 이 오류를 없애는 또 다른 방법인데 시험에서는 맞는 파일이 없으면 그 단어를 인자에서 지웠다. args requests[security] 는 인자 0개(argc=0)를 받았고, ls *.bak 은 인자 없이 실행되어 현재 폴더의 keep.txt 를 나열했다(종료 코드 0). 인자가 사라진 명령이 어떻게 동작할지는 그 명령에 달렸으니, 인자 없이 현재 폴더를 쓰는 명령에서 조심하라는 뜻이다. rm 은 시험하지 않았다.
스크립트 안에서는 오류 뒤에도 계속 간다
s.zsh 에 echo before, args nothing[here], echo after 세 줄을 넣고 실행했더니 zsh 는 ./s.zsh:3: no matches found: nothing[here] 를 찍고도 after 를 실행했고 종료 코드는 0 이었다. zsh -f -c 'echo A; args x[y]; echo B' 도 A, 오류, B 순서였고 종료 코드 0 이었다. 멈춘 것은 그 한 줄의 명령뿐이다. 맞는 게 없다는 오류를 놓치면 뒤 명령이 앞 단계 없이 이어서 돌 수 있으니, 이 글에서 확인하지 않았지만 스크립트에서는 패턴이 든 인자를 항상 따옴표로 감싸는 편이 안전하다. 같은 파일을 bash 로 실행하면 오류 없이 글자를 그대로 넘겼다.
오류를 만났을 때 확인 순서
- 명령에서
[ ],*,?가 든 단어를 찾는다. 대부분 pip 의패키지[선택항목],-e .[dev],*.확장자, URL 이다. - 그 단어를 작은따옴표로 감싸고 같은 명령을 다시 친다(
pip install 'requests[security]'). - 따옴표를 안 쓴 명령이 에러 없이 이상한 결과를 냈다면
echo를 앞에 붙여 셸이 실제로 넘길 인자를 먼저 본다. - 환경: 이 시험은 zsh 5.9, bash 3.2.57, macOS 26.6.2 arm64, 사용자 설정 무시, 인자는
args스크립트로 확인, pip 는 pip 21.2.4(Python 3.9.6) 오프라인 시험 한 가지만 했다. 리눅스의 zsh, 다른 zsh·bash 버전, 대화형 셸의 설정 파일 영향,set -e를 켠 스크립트에서의 동작, fish 나 PowerShell 은 시험하지 않았다.
세 줄 요약
zsh: no matches found는 pip 가 아니라 zsh 가[ ]*?를 파일 패턴으로 풀다 맞는 파일이 없어 명령을 실행하지 않은 것이고, bash 는 같은 단어를 그대로 넘긴다.- 따옴표 없이 맞는 파일이 우연히 있으면 두 셸 모두 오류 없이 파일 이름으로 바꿔 넘기므로
find -name *.py처럼 조용히 틀린다. - 작은따옴표는 파일 유무와 상관없이 글자를 보존했고 nonomatch 는 우연히 맞는 경우를 못 막으며 null_glob 은 인자를 지운다.
To help a reader who met no matches found in zsh see that the shell stopped, not pip, and choose among quotes, a backslash, noglob and nonomatch for their situation.
In my tests, in an empty folder zsh refused to run a command whose word contained brackets, a star or a question mark and matched no file, stopping with exit code 1, while bash and sh passed the word through literally. When a file happened to match, both shells silently replaced the word with that file name, and null_glob removed the argument altogether. Quotes passed the literal text whether or not a file existed.
When the error appears, find the word in the command that contains [ ] * or ?, wrap it in single quotes and run the command again. If you use the same pattern often, make quoting a habit. A global setting in ~/.zshrc is no substitute, because null_glob deletes arguments and nonomatch cannot stop an accidental match.
Contents
- In an empty folder, zsh does not run the command and stops
- The days when it works without quotes are the dangerous ones
- find -name *.py finds only half, without an error
- A ? and & in a URL cause their own trouble
- Four fixes and the trap in each
- Inside a script it keeps going after the error
- What to check when you hit the error
- Three-line summary
One-line summary:
zsh: no matches foundcomes from zsh, not pip: it tried to expand[ ],*or?as a filename pattern, found no matching file and stopped, so wrap that word in single quotes and run the command again.
$ pip install requests[security]
zsh: no matches found: requests[security]
(This is how it looks in an interactive shell. The tests below ran with -c, so the error text is prefixed with zsh:1:.)
You pasted a command straight from an installation guide and got this, which reads as if the package does not exist. It does not mean that. This article puts the same command into zsh 5.9 and bash 3.2.57 side by side to see what actually stopped, when leaving the quotes out goes wrong without any error, and how four fixes differ. Every section ran in a freshly made temporary folder (inside one section I sometimes created and removed a file) on macOS 26.6.2 (arm64), with the user’s settings files ignored through zsh -f and bash --noprofile --norc, and the whole test ran twice with identical output (2026-11-10). A small script (args) that prints the arguments it receives stood in for pip, so only what the shell passed on was visible.
Terms first. A glob is a pattern that names many files at once: * (any number of any characters), ? (any one character) and [abc] (one of the characters in the brackets). The shell turns the pattern into a real list of file names before the command runs. The [security] in requests[security] means “one of s, e, c, u, r, i, t, y”, so to the shell it is not pip’s optional-install (extras) notation but a file name that starts with requests and has one more character.
In an empty folder, zsh does not run the command and stops
| Shell | args requests[security] in a folder with no files |
Exit code |
|---|---|---|
| zsh 5.9 | zsh:1: no matches found: requests[security], command not run |
1 |
| bash 3.2.57 | received one argument, requests[security], unchanged |
0 |
| /bin/sh | same as bash | 0 |
The shell, not the command, produced the error message. The zsh documentation for the NOMATCH option says that if a pattern for filename generation has no matches, it prints an error “instead of leaving it unchanged in the argument list” (the man zshoptions page installed on the Mac says the same), and the option is on by default in zsh. bash does the opposite and leaves the pattern as it is when nothing matches. This article’s interpretation is that someone who used bash is therefore likely to meet this error with the same install command after the Mac default shell became zsh. Several Stack Overflow questions about the same error for requests[security], dask[complete] and pydantic[email] turn up (only the search-result titles were checked; the question bodies could not be opened), and Simon Willison’s April 2020 note also covers pip install -e .[test] being blocked on macOS Catalina with zsh: no matches found: .[test]. I checked that note only through a summary; its remedies are quotes or noglob.
*.txt and rm *.bak behave the same way. In an empty folder zsh stopped on both, with zsh:1: no matches found: *.txt (exit code 1) and zsh:1: no matches found: *.bak, while bash passed the literal *.txt to args and rm printed rm: *.bak: No such file or directory (exit code 1). Nothing was deleted either way.
The days when it works without quotes are the dangerous ones
This time I created one file named requestss in the same folder and ran the same command.
| Shell | args requests[security] |
Exit code |
|---|---|---|
| zsh 5.9 | one argument, requestss |
0 |
| bash 3.2.57 | one argument, requestss |
0 |
The [security] pattern matched requestss (requests plus s), and both shells swapped in that name without an error. An offline test with the real pip (--no-index) showed the same. With quotes, pip read requests[security] as the requirement and followed its dependencies, printing 4 lines containing from requests[security] (lines starting with Requirement already satisfied: …) and 0 error lines, and bash in an empty folder also gave 4. In a folder holding a requestss file, both zsh and bash printed this instead.
ERROR: Could not find a version that satisfies the requirement requestss (from versions: none)
ERROR: No matching distribution found for requestss
That error says the package requestss was not found, and nothing in its wording points to quotes as the cause. When a file happens to match, it looks like “the command behaves strangely”, and once you leave that folder the symptom turns into no matches found. If the same command behaves differently depending on the folder, suspect quotes first.
find -name *.py finds only half, without an error
One common mistake is find . -name *.py. This is the result with a.py in the folder and sub/b.py in a subfolder.
| Command | Output |
|---|---|
find . -name *.py (zsh and bash alike) |
only ./a.py |
find . -name '*.py' |
./a.py, ./sub/b.py |
Without quotes the shell expanded *.py using only the current folder’s a.py and built find . -name a.py, so b.py in the subfolder was missed with no error or warning. If the current folder had held both a.py and b.py, the command became find . -name a.py b.py and stopped with find: b.py: unknown primary or operator (exit code 1). This accident happens in bash just the same as in zsh.
A ? and & in a URL cause their own trouble
? is also a glob, and & sends the preceding command to the background. I typed args http://example.test/p?id=1&lang=ko in an empty folder, and zsh reported only zsh:1: no matches found: http://example.test/p?id=1. That the message stops before the & is the clue. bash left the ? alone, so args received only http://example.test/p?id=1 (the lang=ko after & became a separate variable assignment). Wrapping the whole address in single quotes passed everything through &lang=ko as one argument.
Four fixes and the trap in each
Tested in zsh, in an empty folder, with the same args requests[security].
| Method | How it looks | Empty folder | When a requestss file exists |
|---|---|---|---|
| single quotes | args 'requests[security]' |
literal text | literal text |
| backslash | args requests\[security\] |
literal text | (not tested) |
| noglob | noglob args requests[security] |
literal text | (not tested) |
| nonomatch | setopt nonomatch; args requests[security] |
literal text | became requestss |
Within what was tested, quotes were the only method confirmed to give the same value whether or not a file existed (backslash and noglob were not tested with a file present). nonomatch only makes zsh pass the literal text like bash “when no file matches”, so it cannot prevent the silent misbehavior above. Putting setopt nonomatch into ~/.zshrc therefore removes the error but leaves the risk that results change with the folder (this article did not test a .zshrc file itself, and typed setopt inside the command). noglob is a zsh-only prefix and applies to that one command.
setopt null_glob is another way to get rid of this error, and in the test it deleted the word from the arguments when no file matched. args requests[security] received zero arguments (argc=0), and ls *.bak ran with no arguments and listed keep.txt in the current folder (exit code 0). How a command behaves once its arguments vanish depends on the command, so be careful with commands that use the current folder when given no arguments. rm was not tested.
Inside a script it keeps going after the error
I put three lines in s.zsh: echo before, args nothing[here] and echo after. zsh printed ./s.zsh:3: no matches found: nothing[here] and still ran after, and the exit code was 0. zsh -f -c 'echo A; args x[y]; echo B' also went A, the error, B, with exit code 0. Only that one command stopped. If you miss the no-match error, later commands can run on without the earlier step, so although this article did not test it, quoting every argument that contains a pattern is the safer habit in scripts. Running the same file under bash passed the literal text with no error.
What to check when you hit the error
- Find the words in the command that contain
[ ],*or?. Most are pip’spackage[extra],-e .[dev],*.extensionand URLs. - Wrap that word in single quotes and run the same command again (
pip install 'requests[security]'). - If a command without quotes gave a strange result with no error, put
echoin front first to see the arguments the shell will actually pass. - Environment: this test used zsh 5.9, bash 3.2.57, macOS 26.6.2 arm64, user settings ignored, arguments checked with the
argsscript, and for pip only one offline test with pip 21.2.4 (Python 3.9.6). zsh on Linux, other zsh and bash versions, the effect of settings files in interactive shells, behavior in a script running withset -e, fish and PowerShell were not tested.
Three-line summary
zsh: no matches foundis zsh, not pip, expanding[ ]*?as a file pattern and refusing to run the command because no file matched, while bash passes the same word through.- When a file happens to match without quotes, both shells swap in its name with no error, so things like
find -name *.pygo quietly wrong. - Single quotes kept the text whether or not files existed, nonomatch cannot stop the accidental-match case, and null_glob deletes the argument.