I need to create a bash script to wait for a file to be created. The script will use sleep command inside a while loop to periodically check on a file every 10 seconds. Print out a message while waiting. Display the content of the file once the file is created. Below is what I have tried to implement and it obviously does not work. At this point, I'm not entirely sure how to proceed.
#!/bin/bash
let file=$1
while '( -f ! /tmp/$1)'
do
sleep 10
echo "still waiting"
done
echo "Content of the file $1:"
We use process substitution, <(inotifywait –m –q –e create –-format '%f' ${directory}), to feed the output of inotifywait. Other files might be created in the watched directory while inotifywait waits for the file passed as the input. So, we use read in a while loop to continue waiting for the input file.
The bash wait command is a Shell command that waits for background running processes to complete and returns the exit status. Unlike the sleep command, which waits for a specified time, the wait command waits for all or specific background tasks to finish.
How to Use the Bash Sleep Command. Sleep is a very versatile command with a very simple syntax. It is as easy as typing sleep N . This will pause your script for N seconds, with N being either a positive integer or a floating point number.
wait command will suspend execution of the calling thread until one of its children terminate. It will return the exit status of that command. The sleep command is used to delay the execution of the next command for a given number of seconds, hours, minutes, days. kill is used to terminate a background running process.
The problem here is with the test, not the sleep (as the original question hypothesized). The smallest possible fix might look as follows:
while ! test -f "/tmp/$1"; do
sleep 10
echo "Still waiting"
done
Keep in mind the syntax for a while
loop:
while: while COMMANDS; do COMMANDS; done Expand and execute COMMANDS as long as the final command in the `while' COMMANDS has an exit status of zero.
That is to say, the first argument given to while
, expanding the loop, is a command; it needs to follow the same syntax rules as any other shell command.
-f
is valid as an argument to test
-- a command which is also accessible under the name [
, requiring a ]
as the last argument when used in that name -- but it's not valid as a command in and of itself -- and when passed as part of a string, it's not even a shell word that could be parsed as an individual command name or argument.
When you run '( -f ! /tmp/$1)'
as a command, inside quotes, the shell is looking for an actual command with exactly that name (including spaces). You probably don't have a file named '/usr/bin/( -f ! /tmp/$1)'
in your PATH or any other command by that name found, so it'll always fail -- exiting the while
loop immediately.
By the way -- if you're willing to make your code OS-specific, there are approaches other than using sleep
to wait for a file to exist. Consider, for instance, inotifywait
, from the inotify-tools
package:
while ! test -f "/tmp/$1"; do
echo "waiting for a change to the contents of /tmp" >&2
inotifywait --timeout 10 --event create /tmp >/dev/null || {
(( $? == 2 )) && continue ## inotify exit status 2 means timeout expired
echo "unable to sleep with inotifywait; doing unconditional 10-second loop" >&2
sleep 10
}
done
The benefit of an inotify-based interface is that it returns immediately upon a filesystem change, and doesn't incur polling overhead (which can be particularly significant if it prevents a system from sleeping).
By the way, some practice notes:
"/tmp/$1"
) prevents names with spaces or wildcards from being expanded into multiple distinct arguments.>&2
on echo
commands meant to log for human consumption keeps stderr available for programmatic consumptionlet
is used for math, not general-purpose assignments. If you want to use "$file"
, nothing wrong with that -- but the assignment should just be file=$1
, with no preceding let
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With