스크립트에 명령 옵션을 추가하는 것과 같은 변수를 통해 stdout 및 stderr을 리디렉션하는 방법이 있습니까?
예를 들어 스크립트가 있습니다.
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST
OPT가 -p
아무런 문제없이 대체 되고 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은 dirs 이름이 아닌 리디렉션입니다.
추신. 내가 잘못 가고있을 수도 있지만 스크립트에서 선택적 verbose 또는 non verbose 출력을 만들고 싶습니다. 그러나 비 상세 모드에서도 일부 출력이 필요하므로 스크립트 내 일부 명령에서만 전체 stdout 및 stderr을 리디렉션 할 수는 없습니다.
답변
다른 해결책은 다음과 같습니다.
#!/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
출력을 보려는 명령에만 추가 하십시오.
답변
“어떻게”는 다른 답변에서 잘 설명되었습니다. OP의 코드가 작동하지 않는 “이유”를 설명하고 싶습니다.
기조 연설은 변수 확장 전에 출력 리디렉션이 표시 된다는 것 입니다. 리디렉션은 실제로 변수 확장 후에 수행 되므로 (변수에 저장된 파일 이름으로 출력을 리디렉션 할 수있는 이유) 쉘 은 변수가 확장되기 전에 나중에 처리 할 리디렉션을 식별 합니다.
다시 말해, 일단 변수가 확장 되면 쉘이 경로 재 지정으로 처리 할 명령 문자열의 어느 부분을 이미 식별했기 때문에 경로 재 지정 문자 ( <
또는 >
등)를 고려 하기에는 “너무 늦습니다” .
자세한 내용은 아래에 나열된 1 단계와 3 단계를 참조하십시오.
LESS='+/^SIMPLE COMMAND EXPANSION' man bash
답변
“디렉토리 이름”으로 해석하지 않습니다. >
인용되므로 문자 그대로 처리됩니다 (보다 구체적으로 문자열을 전송합니다 >dev/null 2>&1
.이 문제를 해결하는 유일한 방법은 eval
새 쉘을 사용 하거나 생성하는 것입니다.
귀하의 질문에 언급 된 “자세한”문제에 대해서는 다음과 같이하십시오.
verbose=1
if (( verbose )); then
mkdir -v -p /foo
else
mkdir -p /foo > /dev/null 2>&1
fi
답변
변수에 공백이 많으며 제대로 평가되지 않습니다. eval
이를 설정하는 데 사용할 수 있습니다.
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
eval mkdir $OPT 123/123/123 $TEST
이를 통해 $ OPT를 하나의 ( ) 대신 두 개의 인수 ( -p
및 -v
) 로 나누고 -p -v
$ TEST와 동일하게 할 수 있습니다. 현재 디렉토리에 디렉토리 /dev/null
가있을 가능성이 거의 없으므로 사용하도록 변경되었습니다 dev
.
답변
enzotib의 대답은 좋은 파일 설명자 마술을 사용하지만 더 간단한 해결책은 eval
라인을 사용 하는 것입니다 ( 그러나 프로세스 오버 헤드 가 추가됩니다).
$ rm /tmp/foo
$ ll /tmp/foo
ls: cannot access /tmp/foo: No such file or directory
$ FOO=">/tmp/foo"
$ date $FOO
date: invalid date '>/tmp/foo'
$ cat /tmp/foo
cat: /tmp/foo: No such file or directory
$ eval date $FOO
$ cat /tmp/foo
Thu Dec 13 14:08:17 EST 2018