다음과 같은 파일이 있다고 가정해 보겠습니다 confirmation.sh
.
#!/bin/bash
echo -n "Are you sure [Y/n]? "
read line
case "$line" in
n|N) echo "smth"
;;
y|Y) echo "smth"
;;
esac
다음과 같이 스크립트를 실행하고 싶습니다.
cat confirmation.sh | sh
알겠습니다 Are you sure [Y/n]?
. 스크립트가 중단되었습니다. 문제는 무엇입니까?
답변1
다른 사람들이 말했듯이 이는 파이프에서 읽도록 리디렉션되었기 때문에 평소처럼 터미널에 연결되지 않았기 stdin
때문 입니다. sh
이 문제를 해결하기 위해 할 수 있는 한 가지는 /dev/tty
강제 스크립트를 사용하여 터미널에서 읽는 것입니다. 예를 들어:
#!/bin/sh
read -p "Are you sure [Y/n]?" line </dev/tty
case "$line" in
y|Y) echo "confirmed"
;;
*) echo "not confirmed"
;;
esac
일반적으로 사람들이 입력 스크립트를 작성하는 것을 특별히 방지하려는 경우에만 이 작업을 수행합니다. 예를 들면 다음과 같습니다.
echo Y | sh confirmation.sh
사용자가 메시지가 표시될 때 자동으로 입력하기를 원하더라도 Y
여전히 터미널에서 읽습니다. 이는 이 작업을 수행하기 위해 암호가 필요한 프로그램에서 일반적입니다.
답변2
sh 3<<CONFIRM /dev/fd/3
$(cat ./confirmation.sh)
CONFIRM
sh 3<./confirmation.sh /dev/fd/3
노트:위의 두 가지 예를 수정해 준 @Graeme에게 감사드립니다...
꾸준히 하면 훨씬 쉬울 거예요stdin
분명한.
2<./confirmation.sh . /dev/stderr
또는 터미널 0 1 2가 모두 동일한 파일이므로 다음을 추가하면 됩니다.
read line <&2
그리고 당신 것
cat ./confirmation.sh | sh
좋은 결과.
답변3
이는 내 스크립트에 파이프된 단일 매개변수에 대해 작동합니다.
if [ -p /dev/stdin ]; then set -- "$( cat )"; fi
$1
그런 다음 다른 스크립트 작업과 호환되는 위치 매개변수( )의 파이프 데이터에 액세스할 수 있습니다 .
에서 info test
:
[ -p /dev/stdin ]
:-p FILE
FILE이 존재하고 명명된 파이프이면 참입니다.
답변4
짧은 대답은 할 수 없다는 것입니다. 파이프는 stdout을 stdin으로 리디렉션하므로 파이프 문에서 첫 번째 명령의 출력을 두 번째 명령의 입력으로 리디렉션했기 때문에 대화형 스크립트를 실행할 수 없습니다.
다음과 같이 하고 싶을 수도 있습니다:
cat confirmation.sh > ask.sh && sh ask.sh