xargs 명령과 함께 사용할 때 bash가 별표 문자를 해석하지 않는 이유는 무엇입니까?

xargs 명령과 함께 사용할 때 bash가 별표 문자를 해석하지 않는 이유는 무엇입니까?

내가 이해하는 한, 별표 문자는 *Bash에서 특별한 의미를 가지며, 리터럴 문자를 인쇄하려면 별표를 이스케이프 \*하거나( ) 인용해야 합니다( "*"또는 '*'.

그러나 다음을 시도했을 때 :

$ seq 3 |  xargs -I *  echo *
1
2
3

*위의 예에서 Bash가 설명하지 않는 이유는 무엇입니까? 그러나 아래 예에서는 이를 와일드카드로 해석합니다(현재 디렉터리의 파일과 일치).

$ seq 3 |  xargs -I*  echo * # no space between -I and *
main.py
main.py
main.py

이에 대한 논리를 설명해 주실 수 있나요?

감사해요

답변1

불다했다첫 번째 예에서 별표를 확장합니다.

현재 디렉터리에 파일이 하나만 포함되어 있다고 가정하면 main.py다음과 같은 일이 발생합니다.

$ seq 3 | xargs -I *  echo *
# Expands to:
$ seq 3 | xargs -I main.py echo main.py

echo main.py이를 위해서는 각 입력에 대해 작업을 수행하고 main.py해당 입력으로 대체해야 합니다(때문에 -I main.py). 관찰한 내용은 다음과 같습니다. 세 가지 템플릿이 , 에서 , 으로 echo main.py변경됩니다 .echo 1echo 2echo 3

두 번째 경우에는 단어가 확장되는 것을 방지하기 위해 별표가 바로 옆에 있습니다 -I(패턴과 일치하는 파일이 없기 때문에 -I*).

$ seq 3 | xargs -I*  echo *
# Expands to:
$ seq 3 | xargs -I* echo main.py

*이를 위해서는 템플릿의 (리터럴 별표) 인스턴스를 입력으로 바꾸려면 xargs가 필요합니다 . echo main.py템플릿에는 *자리 표시자가 전혀 포함되어 있지 않으므로 main.py매번 인쇄됩니다.

( failglobBash에서 활성화하거나 zsh에서 기본 설정을 사용하는 경우 일치하는 항목이 없는 glob은 오류를 생성하고 명령이 실행되지 않습니다.)

명령이 두 가지 발생을 모두 보호하는 경우 *첫 번째 시도와 동일한 출력을 얻게 됩니다.

$ seq 3 | xargs -I '*' echo '*'
1
2
3

디렉터리에 여러 파일이 있는 경우 인용되지 않은 파일은 *더 명백한 문제를 일으킬 수 있습니다. 예를 들어, 두 개의 파일이 있고 다음 main.py과 같은 경우 other.py:

$ seq 3 | xargs -I *  echo *
# Expands to:
$ seq 3 | xargs -I main.py other.py echo main.py other.py

명령으로 실행을 시도합니다 xargs(현재 입력 문자열로 대체됨). 이로 인해 "명령을 찾을 수 없음" 오류가 발생할 수 있습니다. 또는 정렬 순서의 두 번째 파일 이름이 다음에서 실행 가능한 프로그램과 일치하는 경우other.py echo main.py other.pymain.pyxargsPATHxargs그 프로그램, 설마 echo.


Bash 확장에서 무슨 일이 일어나고 있는지 어느 정도 가시성을 얻는 데 유용한 방법은 set -o xtrace. 플래그를 설정한 후 다음으로 시작하는 줄의 확장을 볼 수 있습니다 +.

$ set -o xtrace
$ seq 3 | xargs -I * echo *
+ seq 3
+ xargs -I main.py echo main.py
1
2
3

$ seq 3 | xargs -I* echo *
+ seq 3
+ xargs '-I*' echo main.py
main.py
main.py
main.py

$ seq 3 | xargs -I '*' echo '*'
+ seq 3
+ xargs -I '*' echo '*'
1
2
3

관련 정보