파이프가 비어 있는지 확인하고 비어 있으면 데이터에 대해 명령을 실행하려면 어떻게 해야 합니까?

파이프가 비어 있는지 확인하고 비어 있으면 데이터에 대해 명령을 실행하려면 어떻게 해야 합니까?

나는 bash 스크립트에 라인을 파이프했고, 프로그램에 데이터를 공급하기 전에 파이프에 데이터가 있는지 확인하고 싶습니다.

검색해봤는데 test -t 0여기서는 작동하지 않네요. 항상 false를 반환합니다. 그렇다면 파이프라인에 데이터가 있는지 어떻게 확인할 수 있나요?

예:

echo "string" | [ -t 0 ] && echo "empty" || echo "fill"

산출:fill

echo "string" | tail -n+2 | [ -t 0 ] && echo "empty" || echo "fill"

산출:fill

같지 않은위 파이프라인이 출력을 생성하는지 테스트하는 표준/표준 방법은 무엇입니까?입력을 프로그램에 전달하려면 입력을 보존해야 합니다. 이것은 요약된다한 프로세스에서 다른 프로세스로 출력을 파이프하려면 어떻게 해야 합니까? 단, 첫 번째 프로세스에 출력이 있을 때만 수행합니까?이메일을 보내는 데 중점을 둡니다.

답변1

일반적인 셸 유틸리티를 사용하여 파이프의 내용을 볼 수 있는 방법이 없으며 파이프에서 문자를 읽고 다시 넣을 수 있는 이식 가능한 방법도 없습니다. 파이프에 데이터가 있는지 알 수 있는 유일한 방법은 바이트를 읽는 것입니다. 그런 다음 바이트를 대상으로 보내야 합니다.

따라서 다음과 같이 하십시오. 파일 끝이 감지되면 입력이 비어 있을 때 원하는 작업을 수행하고, 바이트를 읽으면 입력이 비어 있지 않을 때 포크합니다. 원하는 작업은 파이프입니다. 바이트를 여기에 넣은 다음 나머지 데이터를 파이프합니다.

first_byte=$(dd bs=1 count=1 2>/dev/null | od -t o1 -A n | tr -dc 0-7)
if [ -z "$first_byte" ]; then
  # stuff to do if the input is empty
else
  {
    printf "\\$first_byte"
    cat
  } | {
    # stuff to do if the input is not empty
  }      
fi

이것ifne유틸리티는 다음에서 비롯됩니다.Joey Hess의 moreutils입력이 비어 있지 않으면 명령이 실행됩니다. 일반적으로 기본적으로 설치되지는 않지만 대부분의 UNIX 변형에서 쉽게 작동하거나 구축됩니다. 입력이 비어 있으면 ifne작업이 수행되지 않고 성공적인 명령 실행과 구별할 수 없는 상태 0이 반환됩니다. 입력이 비어 있을 때 어떤 작업을 수행하려면 명령이 0을 반환하지 않도록 준비해야 합니다. 이는 성공 사례가 구별 가능한 오류 상태를 반환하도록 하여 수행할 수 있습니다.

ifne sh -c 'do_stuff_with_input && exit 254'
case $? in
  0) echo empty;;
  254) echo success;;
  *) echo failure;;
esac

test -t 0이는 표준 입력이 터미널인지 여부를 테스트하는 것과는 아무런 관련이 없습니다. 입력이 가능한지 여부는 전혀 알려주지 않습니다.

254는 여기에서 임의로 선택되었으며 255는 특정 명령을 실행하는 것이 상대적으로 일반적 이므로 exit(-1)(일반적으로 255가 됨 ) 피합니다 .$?-exec(-2)

답변2

간단한 해결책은 ifne명령을 사용하는 것입니다(입력이 비어 있지 않은 경우). 일부 배포판에서는 기본적으로 설치되지 않습니다. 이는 대부분의 배포판에 있는 소프트웨어 패키지의 일부입니다 moreutils.

ifne표준 입력이 비어 있지 않은 경우에만 주어진 명령을 실행하십시오.

표준 입력이 비어 있지 않으면 ifne주어진 명령으로 전달됩니다.

답변3

stdin (0)에 대한 파일 설명자가 열려 있는지 닫혀 있는지 확인하십시오.

[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"

답변4

오래된 질문이지만 나 같은 사람이 발생할 경우를 대비해 내 해결책은 시간 제한을 두고 읽는 것이었습니다.

while read -t 5 line; do
    echo "$line"
done

비어 있으면 stdin5초 후에 반환됩니다. 그렇지 않으면 모든 입력을 읽고 필요에 따라 처리할 수 있습니다.

지원되는 이러한 경우에는 -t입력을 사용하여 데이터를 읽기 전에 입력을 테스트할 수 있습니다 -t0. ( -u0awslinux에서는 STDIN이 필요하고 우분투에서는 STDIN을 가정하므로 STDIN도 지정하십시오.)

if [ $(read -u0 -t0) ]; then ....

그러면 정상적으로 읽기를 시작할 수 있습니다.

에서 help read:

TIMEOUT이 0이면 읽기는 데이터 읽기를 시도하지 않고 즉시 반환되고, 지정된 파일 설명자에서 입력이 가능한 경우에만 성공을 반환합니다.

관련 정보