출력을 분할하지 않고 스크립트 출력을 ls와 같은 명령에 어떻게 전달할 수 있나요?

출력을 분할하지 않고 스크립트 출력을 ls와 같은 명령에 어떻게 전달할 수 있나요?

다음과 같은 스크립트가 있다고 가정해 보겠습니다.

#!/bin/bash
printf '%q\n' "b c"

스크립트 인쇄 실행:

b\ c

명령줄에서.

이제 이름이 지정된 파일이 포함된 디렉터리에서 b c스크립트의 출력을 다음과 같은 명령으로 파이프하고 싶습니다 ls.

$ ls $(./myscript)

여기서 문제는 sum , 즉 두 개의 매개변수 b c로 분할되어 있으며 물론 해당 매개변수를 찾을 수 없다는 것입니다. 이 문제를 피할 수 있는 방법이 있나요? 출력에서 공간을 탈출하는 것만으로도 충분하다고 생각합니다.b\cls

답변1

따옴표 사용:

$ ls "$(./myscript)"

답변2

명령 대체

명령의 출력을 다른 명령의 인수로 전달해야 하는 경우 다음을 사용하십시오.명령 대체. 변수 대체의 경우와 유사하게 명령 대체의 결과는 단어 분할( $IFS기본적으로 의 모든 문자에서 공백으로 분할) 및 와일드카드 확장(파일 이름의 와일드카드 문자)을 거칩니다. 그래서,명령 대체에는 항상 큰따옴표를 사용하십시오.분할 및 와일드카드가 발생하는 것을 원하지 않는 한.

ls -- "$(./myscript)"

--ls스크립트가 로 끝나는 파일 이름을 인쇄하는 경우 처리를 중지하도록 옵션에 지시합니다 -.

텍스트 파일 이름을 인쇄해야 합니다. 스크립트에 추가 참조를 추가하지 마세요.

실제로 인수가 엉망이 될 수 있는 극단적인 경우가 있습니다. 명령 대체는 명령 출력에서 ​​마지막 줄 바꿈을 제거합니다. 따라서 출력이 foo↲bar또는 ( foo↲bar↲개행을 나타내는 데 사용하는)인지 여부에 관계없이 명령에 대한 인수는 입니다. 파일 이름에 줄바꿈이 허용되지만 아무도 이를 사용하지 않기 때문에 실제로 이런 일은 거의 발생하지 않습니다. 그러나 시스템을 해킹하려는 누군가가 파일 이름에 줄 바꿈을 넣을 수 있으므로 이는 보안 위험이 될 수 있습니다.foo↲bar↲↲↲lsfoo↲bar

최종 개행 문자를 처리하려면 개행이 아닌 추가 문자를 출력하도록 명령을 예약하고 명령 대체 결과에서 이를 제거하십시오.

output=$(./myscript; echo a)
output="${output%a}"
ls -- "$output"

여러 파일 이름을 명령에 전달

파일 이름이나 명령줄 인수에 나타날 수 없는 문자 중 하나는 널 바이트입니다. 명령에 전달할 여러 파일 이름이나 기타 인수를 출력하는 안전한 방법은 이를 널 바이트로 구분하고 를 호출하는 것입니다 xargs -0. 이는 Linux, *BSD 및 OSX에서 작동하지만 다른 UNIX 변형에는 부족할 수 있는 POSIX 확장입니다. . 결과 명령줄이 너무 길면 xargs는 이를 분할하고 명령을 여러 번 호출합니다.

… | xargs -0 ls

그렇지 않은 경우 -0다른 xargs일반적인 명령으로 생성할 수 없는 입력 형식이 필요합니다. 입력에 공백 등이 포함되어 있지 않은 경우 \"'.

입력을 인용하는 한 가지 방법 xargs은 최소한 개행, 탭, 공백 및 문자 앞에 백슬래시를 배치하는 것입니다 \"'.

for x in …; do
  printf '%s\n' "$x" | sed -e 's/[  '\''\"]/\\&/g' -e 's/$/\\$/' -e '$ s/\\$//'
done | xargs ls

대괄호 안에 두 개의 공백 문자 대신 sed 명령에 공백과 탭 문자를 입력합니다.

보호되지 않은 대체 및 참조에 대한 추가 설명

보호되지 않은 변수 또는 명령 대체에서는 \[*?와일드카드가 나타나는 각 단어에 대해 4개의 문자가 확장됩니다. 단, 캐릭터만 있어요.[*? 방아쇠와일드카드: 다른 와일드카드가 없는 백슬래시는 변경되지 않고 그대로 유지됩니다. 따라서 현재 디렉터리에 foo, goo및 이라는 세 개의 파일이 포함되어 있으면 bar다음과 같습니다.

  • ls $(echo '?oo bar')ls매개변수를 사용 하여 호출됩니다 foo.goobar
  • ls $(echo '?\oo b\ar')ls매개변수를 사용 하여 호출됩니다 foo.goob\ar

관련 정보