"4800483343"은 디렉터리이고 "file1"과 "file2"는 그 안에 있는 두 개의 파일입니다.
왜 다음과 같은 상황이 발생합니까?
$ ls 4800483343
file1 file2
$ md5sum 4800483343/*
36468e77d55ee160477dc9772a99be4b 4800483343/file1
29b098f7d374d080eb006140fb01bbfe 4800483343/file2
$ mv 4800483343 4800[48]3343
$ md5sum 4800[48]3343/*
md5sum: 4800[48]3343/*: No such file or directory
$ md5sum '4800[48]3343'/*
36468e77d55ee160477dc9772a99be4b 4800[48]3343/file1
29b098f7d374d080eb006140fb01bbfe 4800[48]3343/file2
이 문제를 일으킬 수 있는 다른 문자는 무엇입니까?
답변1
원래 질문에 답하다
대괄호가 쉘 확장을 방지하는 이유
대괄호는 쉘 확장을 방지하지 않지만 따옴표는 방지합니다.
실제로 실행한 명령은 다음과 같았을 것 같습니다.
그러면 다음 파일에서 md5sum이 실행됩니다 dir/
.
$ md5sum d[i]r/*
02fdd7309cef4d392383569bffabf24c dir/file1
db69ce7c59b11f752c33d70813ab5df6 dir/file2
그러면 대괄호가 확장되지 않도록 따옴표가 dir
이동 됩니다.d[i]r
$ mv dir 'd[i]r'
dir
더 이상 존재하지 않는 디렉토리를 찾습니다 .
$ md5sum d[i]r/*
d[i]r/*: No such file or directory
따옴표로 인해 다음 항목은 다음 이름의 새 디렉터리에서 찾을 수 있습니다 d[i]r
.
$ md5sum 'd[i]r'/*
02fdd7309cef4d392383569bffabf24c d[i]r/file1
db69ce7c59b11f752c33d70813ab5df6 d[i]r/file2
수정된 질문에 답하세요
수정된 질문에는 디렉터리 4800483343이 존재하며 다음 명령이 실행됩니다.
mv 4800483343 4800[48]3343
이 명령을 실행할 때 발생하는 일은 glob이 4800[48]3343
기존 디렉터리와 일치하는지 여부에 따라 다릅니다. 일치하는 디렉터리가 없으면 4800[48]3343
자체적으로 확장되고 4800[48]3343
디렉터리 4800483343
를 디렉터리로 이동합니다 4800[48]3343
.
마침내:
이 명령은
md5sum 4800[48]3343/*
glob과 일치하는 디렉터리가 없기 때문에 "해당 파일 또는 디렉터리가 없습니다"라는 오류를 반환합니다4800[48]3343
.따옴표가 전역 확장을 방지하므로 이 명령은
md5sum '4800[48]3343'/*
파일을 올바르게 찾습니다.
글로벌 예시
두 개의 파일을 만들어 보겠습니다.
$ touch a1b a2b
이제 다음 구체를 살펴보십시오.
$ echo a[123]b
a1b a2b
$ echo a?b
a1b a2b
$ echo *b
a1b a2b
답변2
대괄호 표현식은 임의의 수를 나타냅니다.하나의가능한 일치 문자하나의캐릭터 위치. 이 간단한 경험 법칙은 멀티바이트 문자와 [[.
조합 요소 .]]
및/또는 동등 클래스를 처리하기 시작할 때 흐려지는 경향이 있지만 그럼에도 불구하고 아직 이러한 문자에 대한 다중 문자 일치를 완전히 지원하지 않는 프로그램이 많이 있습니다. 모든 로케일에 대해 ASCII 숫자 0-9는 항상 일치하며 대괄호 표현식 내에서 순서대로 정렬됩니다. POSIX에서는 적어도 마지막 숫자가 참이어야 합니다.[[=
=]]
예를 들어:
cd /tmp
for d in 0 1 2 3 4 5 6 7 8 9; do mkdir "$d"; done
ls [0123]
0:
1:
2:
3:
기본적으로 단일 [
대괄호 표현식 ]
쉘 glob은 보다 구체적인 ?
char glob입니다.
echo ?/; echo [2468]/
0/ 1/ 2/ 3/ 4/ 5/ 6/ 7/ 8/ 9/
2/ 4/ 6/ 8/
따라서 쉘 glob은 4800[48]3343
다음 두 개의 현재 디렉터리 파일 이름 중 하나와 일치합니다.
480043343
480083343
...근데 안 어울릴 것 같아...
4800483343
4800843343
4800[48]3343
파일 이름에 리터럴 대괄호를 사용하려면 대괄호 표현식에서 대괄호를 일치시킬 수 있습니다.
touch 4800\[48]3343
echo 4800[[]48[]]3343
4800[48]3343
쉘의 대괄호 와일드카드에도 따옴표가 너무 많이 필요하지 않습니다. 쉘은 목록 컨텍스트에서 glob 표현식의 시작으로 세 문자를 인식합니다.
* ? [
왼쪽 대괄호가 없는 오른쪽 대괄호는 또 다른 문자일 뿐이므로 인용할 필요가 없습니다.
echo ]
]
따라서 쌍의 여는 괄호만 인용하면 항상 문자 그대로 해석됩니다. 그렇지 않으면 언제든지 와일드카드를 완전히 비활성화할 수 있습니다.
set -f
여가 시간에 다시 켜십시오.
set +f
답변3
4800483343
디렉터리 이름 을 로 바꾸면 메타 문자를 이스케이프하기 위해 인용 형식을 사용해야 4800[48]3343
합니다 . [ ]
이것은 모두 작동합니다:
$ ls 4800\[48\]3343/*
$ ls "4800[48]3343"/*
$ ls '4800[48]3343'/*
모두 올바르게 인쇄됩니다.
4800[48]3343/file1 4800[48]3343/file2
그러나 메타 문자를 유지 [
하고 ]
따옴표 없이 그대로 두면 "경로 이름 확장"에 대한 대괄호 설명으로 해석됩니다. bash 매뉴얼에서 "경로 이름 확장"을 검색하면 다음을 찾을 수 있습니다.
[...]는 포함된 문자 중 하나와 일치합니다.
이것이 어떻게 작동하는지 설명하는 텍스트가 더 있습니다. 간단히 말해서:
A [abc] will match ONE character, either an `a`, an `b` or an `c`.
따라서 따옴표가 없는 경우 또는 와 4800[48]3343
일치합니다 . 그 중 어느 것도 디렉토리가 아니며 : 디렉토리가 없기 때문에 확장되지 않습니다 . 더 복잡한 확장은 디렉터리와 일치하며 확장이 작동합니다.480043343
480083343
4800[48]3343
ls 4800[48]3343/*
$ ls 4800$'\133'[48][48]$'\135'3343/*
하지만 어쩌면 나는 여기서 주제에 너무 깊이 들어가고 있을지도 모릅니다. :-)