2

I want make a script that runs in background (with &) and checks if a certain file, the name of which is read from the keyboard, exists in multiple directories, given as parameter.

So the script will run in a while true loop, until the file with the given name is created.

The problem is, when I run the script, what I type from read is taken as a normal terminal cmd.

Here's the script:

#!/bin/bash

echo Type the file name
read fileName


while true
do
    for file in $@
    do
        if find $file -name $fileName | grep -q "$fileName"
        then
            echo The file with name $fileName has been created!!!
            break
        fi
    done
done

If I don't run the script with &, it works fine.

  • 2
    Load the filename as parameter of the script instead of "loading" it via *read*. `scriptname.sh filename` -> in your script the filename will be accesible via `$1` variable ($1 is the first parameter $2 second ... ). http://how-to.wikia.com/wiki/How_to_read_command_line_arguments_in_a_bash_script – Viliam Aboši Apr 11 '17 at 19:29
  • 2
    Since you're in Linux, consider using [**`inotifywait`**](http://unix.stackexchange.com/a/323919/13377) instead of hammering your disk (or cache) with a while loop. – ghoti Apr 11 '17 at 20:16
  • 1
    But to answer your question ... the reason the filename gets taken as shell input is that by backgrounding the script, you detach it from the terminal so that it can't receive input. If you *really* need to provide input which will be processed by a background script, use something like Fred's suggestion. – ghoti Apr 11 '17 at 20:20

3 Answers3

3

I think what you want to do is send only the part of the script that executes without user input to the background. You can do that if you use & inside the script instead of on the command line.

#!/bin/bash

echo Type the file name
read fileName

while true
do
    for file in "$@"
    do
        if find "$file" -name "$fileName" | grep -q "$fileName"
        then
            echo "The file with name $fileName has been created!!!"
            break
        fi
    done
done &

Please note I have added additional quoting to prevent problems in case of files with names containing special characters.

You could make backgrounding the while loop an option too if needed, so that you could select the behavior you prefer when calling the script.

tripleee
  • 175,061
  • 34
  • 275
  • 318
Fred
  • 6,590
  • 9
  • 20
0

I will replace your script with these commands:

  sleep 2; read -p "x=" x; echo "x=$x"

You can get input without changing the "script" with

  echo Hello | sleep 2; read -p "x=" x; echo "x=$x"

If you want the script put together, use

  echo Hello | (sleep 2; read -p "x=" x; echo "x=$x")

Putting the command in the ackground seems to work nice:

  echo Hello | (sleep 2; read -p "x=" x; echo "x=$x")&

When you want to have echo Hello in the background to, use

  (echo Hello | (sleep 2; read -p "x=" x; echo "x=$x"))&
Walter A
  • 19,067
  • 2
  • 23
  • 43
0

You can simplify this by supplying the filename in the command line, if it's acceptable, see the following:

#!/bin/bash

fileName="$1"
shift

while true
do
    for file in "$@"
    do
        if find "${file}" -name "${fileName}" | grep -q "${fileName}"
        then
            echo The file with name ${fileName} has been created!!!
            break
        fi
    done
done

You can just launch by:

$ ./script.sh FILE DIR1 DIR2 &
Andre
  • 1,135
  • 9
  • 20
  • 2
    This will also search for `$fileName` inside `$1` (which is a member of `$@`). Probably not what you intended. – ghoti Apr 11 '17 at 20:20
  • Not clear what you mean... the two scripts are the same, the one I suggest only take the filename as argument (which is $1) – Andre Apr 11 '17 at 20:23
  • 2
    You should *really,* *really* use `"$@"` with proper quoting and similarly quote `"$file"` and `"$fileName"` throughout. – tripleee Apr 11 '17 at 20:39
  • 1
    What @ghoti is saying is you want to `shift` before looping over `"$@"` because otherwise you will search for `$1` in `$1` which is kind of silly. – tripleee Apr 11 '17 at 20:40
  • I think it works like this. Used $1 and shift (otherwise it would get $1 at some stage, cycling over $@). Thanks both of you – Andre Apr 11 '17 at 20:52
  • The braces don't help at all here, you want double quotes around all variables which could ever contain a file name. See further http://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-variable – tripleee Apr 11 '17 at 21:05
  • Thanks for the link, I added the dquotes – Andre Apr 11 '17 at 21:08