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-9)
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
에서 유틸리티 조이 헤스의 moreutils는 입력이 비어 있지 않은 경우 명령을 실행합니다. 일반적으로 기본적으로 설치되지 않지만 대부분의 유닉스 변형에서 사용 가능하거나 쉽게 빌드 할 수 있어야합니다. 입력이 비어 있으면 ifne
아무것도하지 않고 상태 0을 리턴하는데, 이는 성공적으로 실행중인 명령과 구별 할 수 없습니다. 입력이 비어있는 경우 무언가를 수행하려는 경우, 성공 사례가 구별 가능한 오류 상태를 리턴하도록하여 수행 할 수있는 명령이 0을 리턴하지 않도록 배열해야합니다.
ifne sh -c 'do_stuff_with_input && exit 255'
case $? in
0) echo empty;;
255) echo success;;
*) echo failure;;
esac
test -t 0
이것과 아무 관련이 없습니다. 표준 입력이 터미널인지 테스트합니다. 어떤 입력을 사용할 수 있는지 여부에 대해서는 어떤 식 으로든 말하지 않습니다.
답변
간단한 해결책은 ifne
명령 을 사용하는 것입니다 (입력이 비어 있지 않은 경우). 일부 배포판에서는 기본적으로 설치되지 않습니다. moreutils
대부분의 배포판 에서 패키지의 일부입니다 .
ifne
표준 입력이 비어 있지 않은 경우에만 지정된 명령을 실행합니다.
표준 입력이 비어 있지 않으면 ifne
주어진 명령으로 전달됩니다.
답변
오래된 질문이지만 내가 한 것처럼 누군가가 그것을 만난 경우 : 내 해결책은 시간 초과로 읽는 것입니다.
while read -t 5 line; do
echo "$line"
done
stdin
비어 있으면 5 초 후에 반환됩니다. 그렇지 않으면 모든 입력을 읽고 필요에 따라 처리 할 수 있습니다.
답변
stdin (0)의 파일 디스크립터가 열려 있는지 또는 닫혀 있는지 확인하십시오.
[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"
답변
test -s /dev/stdin
명시 적 서브 쉘에서 사용할 수도 있습니다 .
# test if a pipe is empty or not
echo "string" |
(test -s /dev/stdin && echo 'pipe has data' && cat || echo 'pipe is empty')
echo "string" | tail -n+2 |
(test -s /dev/stdin && echo 'pipe has data' && cat || echo 'pipe is empty')
: | (test -s /dev/stdin && echo 'pipe has data' && cat || echo 'pipe is empty')
답변
bash에서 :
read -t 0
입력에 데이터가 있는지 감지합니다 (아무것도 읽지 않음). 그런 다음 입력을 읽을 수 있습니다 (읽기 실행시 입력을 사용할 수있는 경우).
if read -t 0
then read -r input
echo "got input: $input"
else echo "No data to read"
fi
참고 : 타이밍에 따라 다릅니다. 입력 한 시간에 입력에 이미 데이터가 있는지 여부를 감지합니다 read -t
.
예를 들어
{ sleep 0.1; echo "abc"; } | read -t 0; echo "$?"
출력은 1
(읽기 실패, 즉 빈 입력)입니다. echo는 일부 데이터를 기록하지만 첫 바이트를 시작하고 쓰는 속도가 빠르지 read -t 0
않으므로 프로그램이 아직 아무것도 작성하지 않았기 때문에 입력이 비어 있다고보고합니다.
답변
유닉스에서 읽을 수있는 데이터가 있는지 확인하는 쉬운 방법 중 하나는 FIONREAD
ioctl을 사용하는 것입니다.
나는 그것을하는 표준 유틸리티를 생각할 수 없으므로 여기에 그것을하는 사소한 프로그램이 있습니다 ( ifne
moreutils IMHO 😉 보다 낫습니다 ).
fionread [ prog args ... ]
stdin에 사용 가능한 데이터가 없으면 상태 1로 종료됩니다 prog
. 데이터가 있으면 실행 됩니다. prog
지정 하지 않으면 상태 0으로 종료됩니다.
즉시 사용 가능한 poll
데이터에만 관심이있는 경우 통화 를 제거 할 수 있습니다. 파이프뿐만 아니라 대부분의 fd에서 작동합니다.
fionread.c
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>
#ifdef __sun
#include <sys/filio.h>
#endif
#include <err.h>
int main(int ac, char **av){
int r; struct pollfd pd = { 0, POLLIN };
if(poll(&pd, 1, -1) < 0) err(1, "poll");
if(ioctl(0, FIONREAD, &r)) err(1, "ioctl(FIONREAD)");
if(!r) return 1;
if(++av, --ac < 1) return 0;
execvp(*av, av);
err(1, "execvp %s", *av);
}