zip과 rm 명령에서 와일드 카드 문자 *가 다른 이유는 무엇입니까?


58

나는 파일 작업을 수행하는 스크립트를 작성했다. 와일드 카드 연산자 *를 사용하여 유형의 모든 파일에 함수를 적용하고 있지만 얻을 수없는 것이 있습니다. unzip폴더에있는 모든 파일을 이와 같이 할 수 있습니다

unzip "*".zip

그러나 나중에 모든 zip 파일을 제거하려면

rm *.zip

즉, 따옴표를 원하지 않습니다. 반면에 압축 해제는 * 만 주면 작동하지 않습니다 ( "파일이 일치하지 않는다"는 경고를 표시합니다).

왜 다른가요? 나에게 이것은 정확히 동일한 작업처럼 보입니다. 아니면 와일드 카드를 잘못 사용하고 있습니까?

유닉스 의 와일드 카드 소개 는 실제로 이것으로 들어 가지 않으며, rmor zipdocs 에서 아무것도 찾을 수 없습니다 .

Mac (Yosemite)에서 터미널을 사용하고 있습니다.


4
unzip정상적인 for f in *.zip;do...done쉘 루프 가 없으면 이 작업을 수행 할 수 없었습니다 . 유닉스와 같은 이상한 명령 행 UI.
Peter Cordes

@ 피터 당신이 상황을 오해하는 것 같아요. unzip글로브를 아카이브의 내용에 적용합니다. 와일드 카드를 사용하여 bash에서 가져올 수 없습니다. (당신의 F에 대한```해야 할 것 unzip -l archive.zip,하지 ... done`)
알렉시스

@ Alexis : unzip단일 zip 파일 내부에서 globs를 허용하는 것에 대해 알고있었습니다 . 그러나 이것은 다릅니다. 실제로 unzip '*.zip'여러 개의 zip 파일이있는 디렉토리에서 시도 했으며 모든 zip에서 모든 파일을 추출합니다. 내가 말했듯이, 매우 이상합니다. tar그런 작동 모드가 없습니다.
Peter Cordes

1
@Peter I see ... 그렇습니다. 특히 unzip 은 여러 명령 줄 인수를 허용하지 않기 때문에 이상합니다 . 분명히 Windows 전용 구현입니다. OP의 작업 설명을 잘못 해석했습니다.
Alexis

1
@alexis : PKZip은 Windows보다 이전 버전 입니다. 1989 년에 처음 출시 된 DOS 명령 줄 프로그램입니다. Unix 포트는 기본적으로 동일한 cmdline 파싱 코드 인 AFAIK를 사용합니다.
Peter Cordes

답변:


69

상황을 잘 설명했습니다. 퍼즐의 마지막 부분은 unzip와일드 카드 자체를 처리 할 수 있다는 것입니다.

http://www.info-zip.org/mans/unzip.html

인수

파일 [.zip]

...

와일드 카드 표현식은 일반적으로 사용되는 Unix 쉘 (sh, ksh, csh)에서 지원되는 것과 유사하며 다음을 포함 할 수 있습니다.

* 0 개 이상의 문자 시퀀스와 일치

* 와일드 카드를 인용하면 쉘이 확장되지 않도록 unzip와일드 카드 를 보고 자체 논리에 따라 확장하는 것을 처리합니다.

rm반대로 와일드 카드 는 자체적으로 지원하지 않으므로 와일드 카드 를 인용하면 rm대신 파일 이름에서 별표를 찾아야합니다.

unzip *.zip작동하지 않는 이유는 unzip구문이 단순히 여러 개의 zip 파일을 허용하지 않기 때문입니다. 여러 매개 변수가있는 경우 두 번째 및 후속 매개 변수가 아카이브에 파일이 될 것으로 예상합니다.

압축 해제 [-Z] [-cflptTuvz [abjnoqsCDKLMUVWX $ / : ^]] 파일 [.zip] [파일 (들) ...] [-x x 파일 (들) ...] [-d exdir]


6
감사합니다. 내가 올바르게 이해한다면 unzip, 어떤 경우에는 자신의 언어로 말하고 다른 경우에는 일반적인 유닉스 링고입니까?
패트릭

6
옳은. 쉘이하는 일과 프로그램이하는 일을 명심해야합니다.
Jeff Schaller

7
pkzip은 프로그램에 전달 된 와일드 카드를 확장하지 않은 DOS에서 시작되었습니다.
Thorbjørn Ravn Andersen

11
@patrick 한 번에 하나의 파일로만 작동 할 수있는 프로그램으로 여러 파일을 처리하는 유닉스 방식은 루프를 사용하는 것입니다. 예 for f in *.zip ; do unzip -v "$f" ; done. 셸이 파일 이름 확장을 수행하는 이유의 큰 부분은 개별 프로그램마다 필요하지 않은 것입니다. .
cas

24

이 두 명령의 차이점은 인용 *문자입니다. 쉘에서 명령을 호출하고 *인수에 문자를 사용 하면 쉘 자체가 인수를 평가합니다. 이 예를보십시오 :

$ ls
file1.zip  file2.zip  file3.zip  file4.txt

이제 *:

$ ls *.zip
file1.zip  file2.zip  file3.zip

쉘은 와일드 카드를 평가하고 다음과 같이 명령을 빌드합니다.

$ ls file1.zip  file2.zip  file3.zip

인용 된 와일드 카드를 사용하면 (literally)라는 파일로 해석됩니다 *.zip.

$ ls "*".zip
ls: cannot access *.zip: No such file or directory

unzip유틸리티는 인수로 여러 압축 파일을 호출 할 수 없습니다. 그러나 개발자는이를 위해 다른 방법을 선택했습니다. 맨 페이지에서 :

파일 [.zip]

[...] 와일드 카드 표현식은 일반적으로 사용되는 Unix 쉘 (sh, ksh, csh)에서 지원되는 것과 유사합니다. [...] ( 특히 운영 체제 에서 해석되거나 수정 될 수있는 문자를 인용하십시오 . 특히 유닉스와 VMS.)


작성자가 unzip여러 개의 압축 파일을 인수로 허용하지 않고 해당 경로 를 선택한 이유를 알고 있습니까?
David Etler

@DavidEtler 나도 모른다.
혼돈

1
@DavidEtler이지만 빌드 된 unzip의 구문이 zip 파일의 내용으로 간주되는 zip 파일 뒤에 파일 이름을 허용하는 이유는 말할 수 없습니다. 두 번째 zip 파일이 "unzip me"매개 변수인지 또는 "이전 zip 파일을 이전 아카이브에서 압축 해제"했는지 여부는 모호합니다.
Jeff Schaller

@DavidEtler는 개발자들의 생각을 모르지만 그 당시에는 모든 것이 훨씬 느리고 작았습니다. 일반적으로 한 번에 둘 이상의 zip 파일을 다루지 않았습니다. 플로피 디스크는 90 또는 250kB이며 10MB의 디스크 드라이브를 갖게되어 정말 기뻤습니다. 시스템 간 전송뿐만 아니라 압축해야했기 때문에 압축되었습니다.
Joe

6

차이점은 쉘 자체가 글로브를 확장하는 첫 번째 경우입니다.

% cd /                                                       
% echo *
Applications Library Network System Users Volumes bin cores ...
% 

두 번째 경우에는 응용 프로그램 자체가 리터럴 문자를 사용하는 Does Something ™을 사용합니다.

% cd /
% perl -E 'chdir "/tmp" or die; say for glob($ARGV[0])' "*"
com.apple.launchd.aj4FEhYqm5
...

인용되지 않은 경우, 쉘은 먼저 glob를 확장하고 해당 쉘 glob가 확장 된대로 명령이 실행됩니다.


2

명령은 셸에서 처리 된 인수를받습니다.

첫 번째 처리에서 따옴표로 묶지 않은 따옴표 *가 패턴에 맞는 현재 디렉토리 (pwd)의 파일 목록으로 확장됩니다.

echo *.zip

모든 .zip파일을 나열 합니다. 그러나 echo "*".zip"것이다 없습니다 .

첫 번째 처리에서 따옴표 "*"는 확장되지 않으며 인용 부호가 제거 된 후 unzip 명령에 매개 변수로 제공됩니다. unzip 명령은 *.zip다음과 같은 매개 변수를받습니다 :

$ echo unzip "*".zip
unzip *.zip

unzip 명령 *은 파일 목록으로 확장 됩니다.


이 두 명령이 정확히 동일한 최종 작업을 수행 하지 않고 누가 *변경 을 확장 하는지는 흥미 롭습니다 .

unzip "*".zip                ### the command unzip expands `*.zip`.
unzip *.zip                  ### the shell expands `*.zip`.

첫 번째 명령은 *.zip모든 파일을 처리하도록 확장 된 명령을받습니다 . 두 번째 명령 unzip.zip압축 해제 개발자가 둘 이상의 zip파일 확장을 거부하도록 선택했기 때문에 pwd 의 모든 파일 목록을 수신 합니다.


0

zip이 여러 인수를 처리하는 방식 때문에 따옴표가 필요합니다.

rm: 인수 목록에서 모든 파일 제거

zip: 첫 번째 인수에서 파일을 압축 해제하십시오. 나머지 인수에서 파일 만 추출하십시오.

$ ls *.zip
file1.zip  file2.zip  file3.zip
$ unzip *.zip
Archive:  file1.zip
caution: filename not matched:  file2.zip
caution: filename not matched:  file3.zip

보시다시피 file1.zip에서 file2.zip 및 file3.zip을 찾으려고합니다.

한 번에 여러 zip 파일을 추출 할 수 있도록 zip은 glob 자체를 다른 결과로 해석하는 것을 지원합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.