다른 명령이 실패한 경우에만 하나의 명령(원래 입력 유지)으로 파이프하는 방법은 무엇입니까?

다른 명령이 실패한 경우에만 하나의 명령(원래 입력 유지)으로 파이프하는 방법은 무엇입니까?

중복이 아니길 바라지만, 찾아서 답변하려고 실사를 했습니다. 첫 번째 명령이 실패한 경우에만 원시 출력을 두 번째 명령으로 파이프하고 싶습니다.

예를 들어, cat file.txt | command1 || command2command1과 command2는 모두 STDIN에서 읽습니다.

나는 command1이 모든 것을 읽기를 원 cat file.txt하지만, 그것이 실패한다면. command2에서 모든 입력을 실행하고 싶습니다.

편집: 이제 내 질문이 약간 모호하다는 것을 깨달았습니다. 나는 command1과 command2가 모두 STDIN에서 읽힌다고 말했지만, 내가 의미하는 바는 둘 다 cat file.txtSTDOUT을 수신하기를 원한다는 것입니다(반드시 특정 명령일 필요는 없음).

내 원래 소망은 이와 같은 것을 별칭에 넣는 것이었던 것 같습니다. 5개월이 지난 지금 이 문제가 어떻게 해결되었는지 기억이 나지 않습니다. bash 스크립트를 작성하는 것이 가장 가능성이 높습니다.

답변1

스택 교환에 오신 것을 환영합니다! 여기에는 좋은 정보가 많이 있습니다. 먼저 귀하의 세심한 배려에 감사드립니다.

귀하의 주문에서 제가 본 문제는 "질문을 불러일으킨다"는 것입니다. 즉, 시작하기 전에 답을 알고 있다고 가정합니다.

좀 더 자세히 살펴보겠습니다. cat file.txt
"file.txt"의 내용은 STDOUT으로 이동합니다.
"cat" 명령이 오류를 생성하면 STDERR이 실행됩니다.
명령이 완료되면 종료 코드가 설정됩니다. 0 = 성공, 그 외의 것은 오류입니다.

여기서 문제는 출력이 전송될 때까지 실행해야 하는지 여부 command1를 알 수 없다는 것입니다. command2즉, 사라졌습니다.

이것을 비교해보세요:
cat file.txt | sort
이것은 실제로 2개의 명령입니다:
1: cat file.txt 1> temp_file
2: sort < temp_file
음, 실제로 Unix 명령은 아닙니다. 단지 설명을 위한 것입니다.
1: STDOUT을 "tempfile"(즉, 1> 부분)로 보냅니다. 또한 STDERR을 콘솔로 보냅니다.
2: sort 명령을 실행하고 "tempfile"에서 STDIN을 읽습니다. 두 명령 사이에
파이프를 넣으면 |임시 파일이 필요하지 않습니다. 파이프의 의미는 STDOUT을 "cat"에서 "sort"의 STDIN으로 리디렉션하는 것입니다.

문제:
STDOUT을 다른 명령의 STDIN으로 리디렉션하고 싶지만 아직 어떤 명령이 있는지 모르므로 리디렉션할 수 없습니다.

가능한 해결책을 논의하기 전에 몇 가지 배경 지식을 알려드리겠습니다.
Unix에는 원하는 방식으로 명령을 실행하는 방법이 있습니다. 재치 있게:
my_command argument1 argument2 && echo "Success" || echo "Failure"

my_command콘솔에서 STDOUT 및 STDERR을 사용하여 실행한 후(그리고 종료 상태를 반환한 후) 하나 또는 다른 echo를 실행합니다.
&&"마지막 명령이 성공하면 이 작업을 수행하십시오"는
||"마지막 명령이 실패하면 이 작업을 수행하십시오"를 의미합니다

. 원래 명령과 매우 유사합니다. 당신은
cat file.txt | command1 || command2
다음과 같이 바꾸겠습니다:
cat file.txt && command1 || command2
이것은 출력을 제외하고 원하는 모든 것을 제공할 것입니다.

질문 1: 유효한
경우 STDOUT을 읽고 STDERR을 무시해야 합니까? 마찬가지로 실패하면 STDERR을 읽고 STDOUT을 무시해야 합니까? 아니면 두 명령 중 하나가 STDOUT과 STDERR을 모두 읽어야 합니까? 완전성을 기하기 위해 두 가지 질문에 모두 답변하겠습니다. 어느 쪽이든 나중에 처리하기 위해 출력을 저장할 방법이 필요합니다. 일반적으로 임시 파일입니다. 동일한 temp_file에서 STDOUT 및 STDERR을 캡처합니다.cat file.txtcommand1
command2






cat file.txt > /tmp/temp_file 2>&1

STDOUT을 temp_file#1로 캡처하고 STDERR을 temp_file#2로 캡처:
cat file.txt > /tmp/out_file 2 >/tmp/err_file

질문 2: 명령줄에서 파일 이름을 사용할 수 있습니까
?command1command2
command1 temp_file

파일로부터의 리디렉션을 허용하고 command1있습니까 ?command2
command2 < temp_file

STDIN을 실행 command1및/또는 command2읽으시겠습니까?
cat temp_file | command1

참고: 단어 개수 명령은 예시입니다.
wc temp_file
cat temp_file | wc
wc < temp_file
두 번째 형식은 && ||에 문제가 있는 형식이 있을 수 있습니다. 완전성을 위해 여기에 넣겠습니다.

command1결국 무엇을 해야 할지 , command2무엇을 해야 할지 결정해야 합니다 .

이제 이들을 결합할 수 있습니다:
cat file.txt > /tmp/out_file 2>/tmp/err_file && command1 < /tmp/out_file || command2 < /tmp/err_file

그런 다음 임시 파일을 삭제하면
rm /tmp/out_file /tmp/err_file

원하는 결과를 얻을 수 있습니다.
나는 여기의 다른 전문가들이 temp_file을 사용하지 않고도 방법을 알아낼 수 있을 것이라고 확신합니다. 나는 프로그래밍 작업실에 있지도 않고 누가 내 코드를 관리할지 모르기 때문에 일을 간단하고 이해하기 쉽게 유지하는 것을 좋아합니다.

답변2

이를 수행하는 유일한 방법은 출력을 command1파일에 쓰고 읽는 것입니다 command2.

set -o errexit
command1 < file.txt > 1.out
command2 < 1.out

또는

if command1 < file.txt > 1.out
then
    command2 < 1.out
fi

물론 이 시점에서는 파이프라인의 비동기 처리 이점이 사라집니다.

답변3

간단한 방법은 파일 스트림을 file.

command1 < file || command2 < file

또는

if command1 < file; then
    echo 'first command was successful'
else 
    command2 < file
fi

또는 출력하려는 ​​내용에 따라 유사한 구문.

동시에 2개의 명령에서 동일한 파일 스트림을 사용하려면 유사한 방법 tee또는 유사한 방법을 사용해야 합니다. 이는 반환하기 전에 처리를 시작 command2해야 command1하거나 일종의 버퍼링을 사용해야 함을 의미합니다. , 아마도 일부 신호 와 함께 있을 수도 있습니다 . 훌륭하고 확장 가능한 버퍼는 디스크에 있는 파일입니다.

관련 정보