Score:2

Bash script: "read" command not responding

in flag

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.

muru avatar
us flag
Show us how you're executing this function.
Score:4
cn flag

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.

Bubbles avatar
in flag
Yes! Thank you, this has fixed my problem and I understand your solution, which helps me a lot. I'll work on the script to make sure it does exactly what I'm trying to get it to do.
Score:1
cn flag

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.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.