bash: 변수를 사용하여 stderr|stdout 리디렉션 저장

bash: 변수를 사용하여 stderr|stdout 리디렉션 저장

변수를 통해 stdout 및 stderr을 리디렉션하는 방법이 있습니까(예: 스크립트에 명령 옵션 추가)?

예를 들어 다음과 같은 스크립트가 있습니다.

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST

-pOPT가 아무 문제 없이 교체되고 bash가 이를 옵션으로 해석하는 것을 볼 수 있습니다 . 그러나 리디렉션은 디렉터리 이름으로 해석됩니다.

$ ./test.sh 
+ TEST='>/dev/null 2>&1'
+ OPT='-p -v'
+ mkdir -p -v 123/123/123 '>/dev/null' '2>&1'
mkdir: created directory `123/123'
mkdir: created directory `123/123/123'
mkdir: created directory `>/dev'
mkdir: created directory `>/dev/null'
mkdir: created directory `2>&1'

bash에서 $VAR이 디렉토리 이름이 아닌 리디렉션이라고 말할 수 있는 방법이 있습니까?

추신. 제가 잘못된 방향으로 가고 있을 수도 있지만, 스크립트에서 선택적으로 장황한 출력이나 장황하지 않은 출력을 갖고 싶습니다. 그러나 장황하지 않은 모드에서도 일부 출력이 필요하므로 스크립트 내부의 일부 명령에서 전체 stdout 및 stderr을 리디렉션할 수는 없습니다.

답변1

또 다른 해결책은 다음과 같습니다.

#!/bin/bash

verbose=0

exec 3>&1
exec 4>&2

if ((verbose)); then
  echo "verbose=1"
else
  echo "verbose=0"
  exec 1>/dev/null
  exec 2>/dev/null
fi

echo "this should be seen if verbose"
echo "this should always be seen" 1>&3 2>&4

그런 다음 1>&3 2>&4출력을 보려는 명령만 추가하십시오.

답변2

"방법"은 다른 답변에서 잘 설명되었습니다. OP 코드가 작동하지 않는 "이유"를 다루고 싶습니다.

톤은출력 리디렉션이 표시됨앞으로가변 확장. 리디렉션은 실제로구현변수가 확장된 후(출력을 변수에 저장된 파일 이름으로 리디렉션할 수 있음) 쉘은식별하다변수 확장 전 후속 처리를 위한 리디렉션입니다.

즉, 변수가 확장되면 쉘이 명령 문자열의 어느 부분을 리디렉션으로 처리할지 이미 식별했기 때문에 문자( <또는 등) 리디렉션을 고려하는 것은 "너무 늦었습니다".>

자세한 내용은 아래 나열된 1단계와 3단계를 참조하세요.

LESS='+/^SIMPLE COMMAND EXPANSION' man bash

답변3

"디렉터리 이름"으로 해석하지 않고 >인용문으로 해석하므로 문자 그대로 받아들입니다(더 구체적으로 말하면 문자열을 보냅니다 . 이 문제를 해결하는 유일한 방법은 새 쉘을 >dev/null 2>&1사용하거나 생성하는 것입니다 .eval

귀하의 질문에 언급된 "상세한" 문제에 대해서는 다음을 수행하십시오.

verbose=1
if (( verbose )); then
    mkdir -v -p /foo
else
    mkdir -p /foo > /dev/null 2>&1
fi

답변4

변수에 올바르게 평가되지 않는 공백이 많이 있습니다. eval설정하려면 이 정보가 필요합니다 .

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
eval mkdir $OPT 123/123/123 $TEST

이를 통해 $OPT를 하나( ) 대신 두 개의 매개변수( -p및 ) 로 분할 하고 $TEST와 동일하게 할 수 있습니다. 또한 현재 디렉터리에 디렉터리가 없을 가능성이 높으므로 사용하도록 변경되었습니다 .-v-p -v/dev/nulldev

관련 정보