Waiting for a file to be created in Bash

I need to create a bash script to wait for a file to be created. The script will use the sleep command inside the while loop to periodically check the file every 10 seconds. Print the message while waiting. Display the contents of a file after creating the file. Below I tried to implement and obviously does not work. At the moment, I'm not quite 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:" 
+6
source share
1 answer

The problem here is testing, not a dream (as suggested in the original question). The smallest possible fix might look like this:

 while ! test -f "/tmp/$1"; do sleep 10 echo "Still waiting" done 

Keep in mind the syntax of the while :

 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, the first argument given in while extending the loop is a command; it must follow the same syntax rules as any other shell command.

-f valid as an argument to test - a command that is also available under the name [ , requiring ] as the last argument when used in this name - but it is not valid as the command itself, and when it is passed as part of a line, it is not even a shell word that can be parsed as the name or argument of a single command.

When you run '( -f ! /tmp/$1)' as a command, inside quotation marks, the shell looks for the actual command with that name (including spaces). You probably don't have a file named '/usr/bin/( -f ! /tmp/$1)' in your PATH or any other command with that name, so it always fails - it will exit the while immediately.


By the way, if you want to make your code OS-specific, there are other approaches besides using sleep to wait for the file to exist. Consider, for example, 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 advantage of the inotify-based interface is that it immediately returns when the file system changes and does not bear the overhead of polling (which can be especially significant if it prevents the system from sleeping).


By the way, some practical notes:

  • Designating decompositions in file names (ie, "/tmp/$1" ) prevents names with spaces or wildcards from being spaced into several different arguments.
  • Using >&2 on echo commands designed for logging in for human consumption allows stderr to be available for programmatic consumption
  • let used for math , not general purpose. If you want to use "$file" , there is nothing wrong with that - but the assignment should just be file=$1 , without the previous let .
+11
source

All Articles