환경 변수에서 명령 인수를 올바르게 이스케이프하는 방법

환경 변수에서 명령 인수를 올바르게 이스케이프하는 방법

find두 명령의 출력을 병합하여 다음 연산자로 파이프하려고 합니다 . 두 실행에 전달된 매개변수는 find매우 유사하므로 그대로 유지하고 싶습니다.

FIND_CMD_ARGS="-type f \( -iname \*.m -o -iname \*.swift \) -print0"
CMD_OUTPUT=`{ find $PROJECT_PATH -not -path '*/Pods/*' $FIND_CMD_ARGS; find . -path '*/Pods/MyProject*/*' $FIND_CMD_ARGS }`

어떤 이유로 이것이 작동하지 않습니다. 이것이 내가 얻은 결과입니다.

find: illegal option -- n
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
find: -type f \( -iname \*.m -o -iname \*.swift \) -print0: unknown primary or operator

생각하다args문제는 환경 변수에서 이스케이프가 수행되는 방식과 관련이 있지만 FIND_CMD_ARGS올바른 방법을 알 수 없습니다.

어떤 아이디어가 있나요? 감사해요!

답변1

변수에 여러 매개변수를 저장하려면 배열을 사용하세요.

find_args=(-type f \( -iname \*.m -o -iname \*.swift \) -print)
cmd_output=$(
  find "$PROJECT_PATH" ! -path '*/Pods/*' "${find_args[@]}"
  find . -path '*/Pods/MyProject*/*' "${find_args[@]}"
)

나도

  • 변수 확장 주위에 누락된 따옴표를 추가했습니다.
  • 변수 이름을 소문자로 변경합니다. 환경 변수가 아닌 것처럼 보입니다(어차피 이제는 배열이므로 환경으로 내보낼 수 없습니다).
  • 비표준을 -not표준으로 변경합니다 !( -iname또 다른 비표준 술어입니다).
  • $(...)더 이상 사용되지 않는 이전 형식 대신 명령 대체 형식을 사용하십시오 `...`.
  • NUL 바이트를 저장할 수 없는 -print0변수로 변경하세요 .-printbash

또 다른 접근 방식은 함수를 선언하는 것입니다.

myfind() {
  find "$@" -type f \( -iname \*.m -o -iname \*.swift \) -print
}
cmd_output=$(
  myfind "$PROJECT_PATH" ! -path '*/Pods/*'
  myfind . -path '*/Pods/MyProject*/*'
)

이제 이 변수에 대해 할 수 있는 일은 많지 않습니다. 대신 $cmd_output.-print-print0

bash 4.4 이상에서는 대신 배열을 사용하고 다음을 사용할 수 있습니다.

myfind() {
  find "$@" -type f \( -iname \*.m -o -iname \*.swift \) -print0
}
readarray -td '' files < <(
  myfind "$PROJECT_PATH" ! -path '*/Pods/*'
  myfind . -path '*/Pods/MyProject*/*'
)

관련 정보