"bash -c"에 매개변수 추가

"bash -c"에 매개변수 추가

Bash를 통해 다음과 같이 명령을 실행하고 싶다고 가정해 보겠습니다.

/bin/bash -c "ls -l"

Bash 매뉴얼 페이지에 따르면 다음과 같이 실행할 수도 있습니다.

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

하지만 작동하지 않는 것 같습니다(무시되는 것 같습니다). 내가 뭔가 잘못하고 있는 걸까요, 아니면 매뉴얼 페이지를 잘못 해석하고 있는 걸까요?

남성에 관한 관련 인용문:

-c 옵션이 있으면 문자열에서 명령을 읽습니다. 문자열 뒤에 매개변수가 있으면 $0부터 시작하는 위치 매개변수에 할당됩니다.

그리고

A - 옵션의 끝을 나타내며 추가 옵션 처리를 비활성화합니다. -- 이후의 모든 인수는 파일 이름 및 인수로 처리됩니다.

답변1

매뉴얼 페이지에 대한 해석이 잘못되었습니다. 먼저 옵션의 끝을 나타내는 부분은 --하려는 작업과 관련이 없습니다. -c그 시점부터 나머지 명령줄은 덮어쓰기되어 더 이상 bash의 옵션 처리를 거치지 않습니다. 즉, --bash에서 옵션 끝 표시로 처리되는 대신 명령에 전달된다는 의미입니다.

두 번째 오류는 추가 인수가 명령에 인수로 전달되지 않고 시작된 셸 프로세스에 위치 인수로 할당된다는 것입니다. 따라서 수행하려는 작업은 다음 중 하나로 수행할 수 있습니다.

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

첫 번째 경우에는 echo 인수가 명시적으로 전달되고 $0, $1두 번째 경우에는 "$@""$0을 제외한 모든 위치 인수"에 일반 확장이 사용됩니다. 이 경우에는 사용할 무언가를 전달해야 한다는 점에 유의하세요 $0. 저는 "bash"를 선택했습니다. 왜냐하면 이것이 $0일반적이지만 다른 것도 가능하기 때문입니다.

이렇게 하는 이유는 제공한 인수를 나열한 명령에 직접 전달하는 것보다 다음과 같습니다. 문서에 "명령에스문자열에서 ""(복수형)를 읽습니다. 즉, 이 프로그램을 사용하면 다음을 수행할 수 있습니다.

/bin/bash -c 'mkdir -p -- "$1" && cd -P -- "$1" && touch -- "$2"' bash dir file

그러나 원래 목표를 달성하는 더 좋은 방법은 다음을 env대신 사용하는 것일 수 있습니다 bash.

/usr/bin/env -- "ls" "-l"

셸이 제공하는 기능이 필요하지 않다면 사용할 이유가 없습니다. env이 경우 더 빠르고 간단하며 입력이 덜 필요합니다. 그리고 쉘 메타 문자나 공백이 포함된 파일 이름을 안전하게 처리할 수 있는지 확인하기 위해 너무 열심히 생각할 필요가 없습니다.

답변2

귀하의 목표가 무엇인지는 잘 모르겠지만 단지 구축하고 싶다면루브 골드버그 기계– “아주 간단한 작업을 매우 복잡한 방식으로 수행하기 위해 의도적으로 과도하게 설계되거나 과도하게 설계된 장치, 발명, 장치 또는 장치” – 그런 다음 시도해 보십시오.

sh -c 'ls $0' -l

또는

sh -c 'ls $1' supercalifragilisticexpialidocious -l

심지어

sh -c 'ls -$0' l

이러한 작업이 어떻게 작동하는지 이해할 수 있어야 합니다.신 괴짜의 대답. ~처럼 데릭 마하르 댓글, 스크립트 매개변수(다음 명령 문자열  -c)는 큰따옴표 대신 작은따옴표로 묶어야 한다는 점을 강조해야 합니다. 그렇지 않으면 상위 셸(위 명령줄을 입력한)은 상위 셸의 컨텍스트에서 스크립트 매개변수의 위치 인수를 구문 분석합니다. 예를 들어,

$ set -- The quick brown fox
$ sh -c 'echo "$0" "$1"' foo bar baz
foo bar
$ sh -c "echo '$0' '$1'" foo bar baz
bash The

답변3

그것은 그 모든 것보다 간단하고 당신은 꽤 가깝습니다.

전체 명령이 단일 문자열로 전달되도록 공백을 이스케이프 처리합니다. 스크립트는 다음과 같습니다.

bash -c "ls\ -l\ $@"

이스케이프되지 않은 공백으로 구분하여 추가 명령을 추가할 수 있습니다.

#                  ↓            unescaped
bash -c "cd\ ~/junk ls\ -l\ $@"
#          ↑↑         ↑↑  ↑↑    escaped

junk이 명령에서 와 사이의 공백은 ls이스케이프 처리되지 않은 유일한 공백이므로 두 명령을 구분하는 역할을 합니다.

관련 정보