답변:
그 이유는 다음과 같이 작성해야합니다.
rm -- *.txt
그리고 아닙니다
rm *.txt
.txt
현재 디렉토리 의 어떤 파일도로 시작하는 이름을 보장하지 않는 한 -
.
에서:
rm <arg>
<arg>
로 시작하면 옵션으로 간주 -
되거나 그렇지 않으면 제거 할 파일로 간주됩니다. 에서
rm- <arg>
arg
시작 여부에 관계없이 항상 제거 할 파일로 간주됩니다 -
.
그것도 마찬가지입니다 sh
.
로 시작하는 스크립트를 실행할 때
#! /bin/sh
일반적으로
execve("path/to/the-script", ["the-script", "arg"], [environ])
시스템은 다음과 같이 변환합니다.
execve("/bin/sh", ["/bin/sh", "path/to/the-script", "arg"], [environ])
은 path/to/the-script
일반적으로 스크립트 작가의 제어하에있는 것이 아닙니다. 저자는 스크립트 사본이 어디에 저장 될 것인지 또는 어떤 이름으로 저장 될 것인지 예측할 수 없습니다. 특히, 그것들 path/to/the-script
이 호출되는 것이 시작 되지 않는다는 것을 보장 할 수 는 없습니다 -
(또는 이것 +
으로도 문제입니다 sh
). 우리는 이유 가 필요-
옵션의 끝을 표시하려면 여기를.
예를 들어, 내 시스템 zcat
(실제로 다른 스크립트와 마찬가지로)은 해당 권장 사항을 따르지 않은 스크립트의 한 예입니다.
$ head -n1 /bin/zcat
#!/bin/sh
$ mkdir +
$ ln -s /bin/zcat +/
$ +/zcat
/bin/sh: +/: invalid option
[...]
지금 당신은 왜 요청할 수 있습니다 #! /bin/sh -
하지 #! /bin/sh --
?
#! /bin/sh --
POSIX 쉘과 함께 작동 하지만 #! /bin/sh -
더 이식성이 뛰어납니다. 특히 고대 버전의 sh
. sh
치료 -
로 및 끝 옵션 선행 getopt()
과의 일반적인 사용하는 것은 --
오랜 시간에 따라 옵션의 끝을 표시합니다. Bourne 쉘 (70 년대 후반)이 인수를 구문 분석하는 방식으로 옵션이 시작된 경우 첫 번째 인수 만 고려되었습니다 -
. 이후의 모든 문자 -
는 옵션 이름으로 취급됩니다. 뒤에 문자 -
가 없으면 옵션이 없었습니다. 멈 췄고 이후의 Bourne과 같은 껍질 -
은 옵션의 끝을 표시하는 방법으로 인식 됩니다.
Bourne 쉘에서 (그러나 현대 Bourne과 같은 쉘에서는 아님) #! /bin/sh -euf
옵션에 대한 첫 번째 인수 만 고려되었으므로 문제를 해결할 수도 있습니다.
이제 우리는 여기에 현란한 존재라고 말할 수 있으며, 위의 기울임 꼴로 필요성 을 쓴 이유이기도합니다 .
-
하거나 +
이름이 -
또는로 시작되는 디렉토리에 스크립트를 넣지 않습니다 +
.execvp()
/ execlp()
유형 함수 에서 발생하는 경우가 더 많습니다 . 그리고이 경우, 일반적으로 그들을 호출 중 하나로 the-script
이에서보고되기 위해서는 $PATH
이 경우의 경로 인수 execve()
시스템 호출은 일반적으로 시작됩니다 /
(하지 -
않고 +
) 또는 ./the-script
당신이 원하는 경우 the-script
현재 디렉토리에서 실행하는 (그리고 다음 경로로 시작 ./
하지, -
나 +
) 중 하나.이제 이론적 정확성 문제 옆에 모범 사례#! /bin/sh -
로 추천 된 또 다른 이유 가 있습니다 . 그리고 여러 시스템이 여전히 setuid 스크립트를 지원했던 시점으로 돌아갑니다.
다음을 포함하는 스크립트가있는 경우 :
#! /bin/sh
/bin/echo "I'm running as root"
그리고 그 스크립트는 -r-sr-xr-x root bin
일반 사용자가 실행할 때 해당 시스템에서 setuid root ( 권한 과 같은)입니다 .
execve("/bin/sh", ["/bin/sh", "path/to/the-script"], [environ])
로 수행됩니다 root
!
사용자가 심볼릭 링크를 생성하여로 /tmp/-i -> path/to/the-script
실행 -i
하면 대화 형 쉘 ( /bin/sh -i
) 이로 시작 됩니다 root
.
은 -
(는 주위에 작동하지 않을 것이라는 점을 해결할 것이다 경쟁 조건 문제 , 또는 사실 sh
일부처럼 구현 ksh88
기반 것들 않고 스크립트 인수를 조회 할 /
의 $PATH
생각을).
요즘은 거의 모든 시스템 지원이 setuid 스크립트 더 이상하고 (안 기본적으로 보통) 아직도 그들 중 일부는, 일 최대 종단 A execve("/bin/sh", ["/bin/sh", "/dev/fd/<n>", arg])
(여기서 <n>
주위에이 문제와 모두 작동하는 스크립트를 읽기위한 열린 파일 기술자입니다) 경쟁 조건.
Bourne과 같은 쉘뿐만 아니라 대부분의 인터프리터에서도 비슷한 문제가 발생합니다. 비 Bourne 형 쉘은 일반적으로 -
옵션 끝 마커로 지원 --
하지 않지만 일반적으로 (적어도 최신 버전에서는) 지원합니다.
또한
#! /usr/bin/awk -f
#! /usr/bin/sed -f
다음 인수는 인수로 간주됩니다으로 문제가없는 -f
어떤 경우에 옵션,하지만 경우 여전히 일을하지 않는 path/to/script
것입니다 -
(이 경우, 가장 sed
/ awk
구현 sed
/ awk
로부터의 코드를 읽지 않는다 -
파일이지만 stdin에서 대신).
또한 대부분의 시스템에서 다음을 사용할 수 없습니다.
#! /usr/bin/env sh -
#! /usr/bin/perl -w --
대부분의 시스템에서 shebang 메커니즘은 인터프리터 경로 다음에 하나의 인수 만 허용 합니다.
#! /bin/sh -
vs 사용 여부에 #!/bin/sh -
관해서는 맛의 문제 일뿐입니다. 나는 인터프리터 경로를 더 잘 보이게하고 마우스 선택을 쉽게하기 때문에 전자를 선호합니다. 있다 공간이 고대의 유닉스 버전에 필요하다고 말한다 전설 되지만 확인 된 적이 AFAIK는.
유닉스 세방에 대한 아주 좋은 참고 자료는 https://www.in-ulm.de/~mascheck/various/shebang 에서 찾을 수 있습니다
bash
는 다른 모든 쉘과 같은 옵션을 허용합니다. 하는 본 같은과 POSIX 쉘 인, bash
모두 수용 #! /bin/bash -
하고 #! /bin/bash --
.