Bash script: "read" command not responding

I am writing a bash script that will

  1. Downlaod a website's html code into a file "index.html"
  2. Ask user for file type and search "index.html" for number of matched file types

This is the function that will complete step 2:

1. function findFiles() {
2.      echo "Enter file type to search for (include '.') || Type EXIT to terminate program "
3.      read fileType
4.
5.      while [[ "$fileType" != "EXIT" ]];
6.      do
7.          if [[ $(grep -q $fileType index.html) = 1 ]]; then
8.              grep -F "$fileType" index.html >> foundFiles.txt
9.          fi
10.     done
11.
12.     rm index.html
13. };

When executed, line 3 prompts for user input but does not respond when I hit enter, example follows:

2021-09-26 12:41:06 (2.66 MB/s) - ‘index.html’ saved [94126]

Enter file type to search for (include '.') || Type EXIT to terminate program 
.pdf
.txt



foo
AAAA

I have tried declaring a local variable $fileType first, using read -p and putting a semicolon at the end of line 3. The result is always the same and I have not been able to find a solution. I'm aware that what follows line 3 is flawed, but I just would only like help with line 3 as the following lines are something I would like to work on myself to learn more about bash scripting.

Any ideas are appreciated.


Solution 1:

It isn't supposed to respond. It is doing exactly what it should: it reads the input and assigns it to the variable fileType. However, you then have a while loop which is checking the value of a variable that never changes:

while [[ "$fileType" != "EXIT" ]];

Since the value of $fileType is set only once and before the while loop, that while becomes an infinite loop unless you pass EXIT on the first try. In any case, your script wouldn't work anyway since the output of grep -q pattern file will never be 1. In fact, it will always be empty since that's what grep -q does. I suspect you meant to check the exit status of the command but, even that is pointless: there is no benefit in reading the entire file once with grep -q only to then read it all over again with grep -F.

Here's a working version of your function:

function findFiles() {
  while [[ "$fileType" != "EXIT" ]];
  do
    echo "Enter file type to search for (include '.') || Type EXIT to terminate program "
    read fileType
    grep -F "$fileType" index.html >> foundFiles.txt
  done
     rm index.html
 };

Or, if you want to avoid creating an empty foundFiles.txt if no matches were found, you can try:

function findFiles() {
  while [[ "$fileType" != "EXIT" ]];
  do
    echo "Enter file type to search for (include '.') || Type EXIT to terminate program "
    read fileType
    if grep -qm1 "$fileType" index.html; then
      grep -F "$fileType" index.html >> foundFiles.txt
    fi
  done
     rm index.html
 };

The -m ensures the grep exits after the first match so you don't need to read the whole file twice. Note how I am not using the command substitution ($(command)) syntax since I am checking that the command was successful, and not trying to use its output.

Solution 2:

You seem to be catching yourself in an endless loop. If the user did not type "EXIT", then the while loop will go on forever. Any additional text you type is just being echoed to the terminal.