0

I wrote a shell script using bash built-in command select to create selection menu. It works well when invoking by bash directly. But if I use pipe | such as cat script.sh | bash, the select function will not work.

For example, code snippet shows

#!/usr/bin/env bash

arr=("Red Hat" "SUSE" "Debian")
PS3="Choose distribution:"

result=${result:-}

select item in "${arr[@]}"; do
    result="${item}"
    [[ -n "${result}" ]] && break    
done

echo "Result is ${result}"
unset PS3

Directly using bash script.sh, works well.

$ bash /tmp/test.sh 
1) Red Hat
2) SUSE
3) Debian
Choose distribution:1
Result is Red Hat

Using pipe |, it will output

$ cat /tmp/test.sh | bash
1) Red Hat
2) SUSE
3) Debian
Choose distribution:1) Red Hat
2) SUSE
3) Debian
Choose distribution:Choose distribution:Choose distribution:

This makes the script not work.

I don't know why? Does select do not suppoer pipe | or anything else?

halfer
  • 19,824
  • 17
  • 99
  • 186
  • You've created a situation where your script is trying to read from itself, since it inherits its standard input from the `bash` process that runs it. Don't run an interactive script like this. – chepner Sep 25 '17 at 11:45

1 Answers1

2

select reads from stdin. stdin is coming from the pipe. If you want to get data from the tty, you can try:

#!/usr/bin/env bash

arr=("Red Hat" "SUSE" "Debian")
PS3="Choose distribution:"

result=${result:-}

select item in "${arr[@]}"; do
    result="${item}"
    [[ -n "${result}" ]] && break    
done < /dev/tty                      #  <------------------

echo "Result is ${result}"
unset PS3
William Pursell
  • 204,365
  • 48
  • 270
  • 300