6

I have a problem here. Seems like my Bash script is ignoring everything that is between do and done. Don't know why, maybe you will see the problem. Thanks in advance.

katalogas=$1
find $katalogas -type f -mtime +3 | while read $failai
do
read -p "Run command $foo? [yn]" answer
if [[ $answer = y ]] ; then
  rm $failai
fi
done
Michael Jaros
  • 4,586
  • 1
  • 22
  • 39
demboz11
  • 917
  • 2
  • 9
  • 15

3 Answers3

11

Try to replace

read -p "Run command $foo? [yn]" answer

by

read -p "Run command $foo? [yn]" answer </dev/tty

to avoid reading from stdin.

Update with Will's suggestion:

katalogas="$1"
read -p "Run command $foo? [yn]" answer
if [[ $answer = y ]] ; then
  find "$katalogas" -type f -mtime +3 | while read failai
  do
    rm "$failai"
  done
fi
Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • 1
    Now It's better, but not actually what I want. I want to confirm Y only one time, sadly, but this way script keeps asking on every single file – demboz11 May 03 '15 at 20:25
  • 1
    You need to move your `read` code outside of the loop, then. You didn't really provide enough context to what's going on in the rest of the script, but the way your code is written, it asks the question for every file we're looping through. – Will May 03 '15 at 20:28
  • Thank you very much, Cyrus and Will! :) – demboz11 May 03 '15 at 21:43
1

So the first problem I see is that your while read $failai should be while read failai (without the $). Try this:

katalogas="$1"
find "$katalogas" -type f -mtime +3 | while read failai; do
    read -p "Run command ${foo}? [yn]" answer
    if [[ "$answer" = "y" ]]; then
        echo labas
    fi
done

As far as prompting for yes or no, though, I usually use something like this:

function prompt_yn()
{
    local default=""
    local prompt="y/n"
    local input

    # If $2 specifies a default choice, configure options accordingly.
    if [[ "${2:-}" = "Y" ]]; then
        prompt="Y/n"
        default="Y"
    elif [[ "${2:-}" = "N" ]]; then
        prompt="y/N"
        default="N"
    fi

    # Prompt the user until they give an appropriate answer.
    while true; do
        read -p "$1 [${prompt}] " input
        [[ -z "$input" ]] && input="$default"

        case "$input" in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

So, if you used the code above, your code would look like this:

katalogas="$1"
find "$katalogas" -type f -mtime +3 | while read failai; do
    if prompt_yn "Run command ${foo}?"; then
        echo labas
    fi
done

You can also add a "Y" or a "N" after the "Run command ${foo}?" to specify a default value if the user just presses Enter.

EDIT: It seems I missed the point about part of this. Cyrus's answer is the solution to the read not working inside the loop. This StackOverflow post explains it well also. However, based on your comment, @semkius, it seems you only want to ask the question once, outside of the loop.

Will
  • 24,082
  • 14
  • 97
  • 108
  • 1
    Your `prompt_yn` is really nice, but it kind of misses the point in the context of this question. It does not fix the problem of reading from the pipeline just as the OP's code (check Cyrus' answer). – Michael Jaros May 03 '15 at 20:24
  • I don't think Cyrus' answer addresses the problem. The read block isn't being entered because he puts a '$' before the variable name for the `while read`. Since he doesn't quote it or anything, it just evaluates to `while read ` causing the loop not to occur. I've never seen the need to redirect` /dev/tty` into read, what's wrong with `stdin` here?. – Will May 03 '15 at 20:27
  • 1
    You are right about that statement probably not doing what the OP intended, but that does not stop the loop. See `help read`: "If no NAMEs are supplied, the line read is stored in the REPLY variable." – Michael Jaros May 03 '15 at 20:32
  • 1
    Minimal example for a quick test: `echo x"$nothing"x ; find | while read $nothing ; do echo y ; sleep 1 ; done` – Michael Jaros May 03 '15 at 20:35
  • Ah cool, I just tested it, you're right, sorry. I wonder if `stdin` being in-use for the `while read` prevents `read` from working properly in the loop. It also seems that OP didn't really want to do it inside the loop at all. I guess I should edit/delete this? – Will May 03 '15 at 20:38
  • 1
    No problem. You could add some info from these comments to your answer if you like, but I woudln't say it's necessary, and I wouldn't delete it either. Answers that provide additional info around the actual topic can often be valuable to readers too. – Michael Jaros May 03 '15 at 20:43
  • 1
    Thanks! I edited and linked to Cyrus's answer and upvoted his post. I love the collaborative effort of this :) – Will May 03 '15 at 20:44
0

use the command reset and then execute your shell script.

singingsingh
  • 1,364
  • 14
  • 15