Reputation: 20717
I've a shell script which list files of a folder and then do an action on them(print into a PDF), but very often I get a blank PDF. If I remove the generated PDF, the new PDF is always correctly generated.
I've the impression that is because my script started to print BEFORE the file has been fully copied(the copy is made through the OS explorer, with a save as, or just copy-paste).
It's absolutely not me which manage when someone add a new file, the copy comes from users which uses a network share.
so is there a way to have something like this?
for inputFile in `ls -l $SearchPattern | grep ^- | awk '{print $9}'`
do
//CHECK_THAT_THE_FILE_HAS_ALREADY_BEEN_FULLY_SAVED_ONCE
//DO_MY_PRINT_HERE
done
Upvotes: 1
Views: 5858
Reputation: 20717
I ended by using
for inputFile in `find $SearchPattern2 -maxdepth 1 -type f -cmin +1 -iname "*.pdf"`
the -cmin +1 indicate to find, that is has to list only file with the modification time >1min ago.
It's not 100% safe, but it will handle all my case with a lot of margin.
I didn't find how to do this in seconds
Upvotes: 1
Reputation: 7180
As someone pointed out, using the file modification time might be useful. I've quickly done this script that might be useful. It will wait until 5 seconds have passed since the last modification time of a given file:
#!/bin/bash
function getTimeFromLastChange() {
file=${1}
let lastAccess=$(stat --format=%Y ${file})
let now=$(date +%s)
let timePassed=$((now - lastAccess))
echo ${timePassed}
}
file=./test
while [ true ]; do
let lastChange=$(getTimeFromLastChange ${file})
if [ "${lastChange}" -lt 5 ]; then
echo "waiting"
sleep 1
else
echo "done"
exit
fi
done
echo ${timePassed}
The key here is the "getTimeFromLastChange" function that uses stat (http://linux.die.net/man/1/stat) to get the last modification time for the given file in seconds since the unix epoch time. Then, it will get the current time using date (http://linux.die.net/man/1/date) (again, in seconds since the unix epoch time), substract them, and figure the total amount of seconds since the last modification time.
The main loop will wait until some "safe" amount of seconds have passed by. So you can try tunning this parameter and print the files that were written/modified some N amonut of seconds ago.
A sample run:
marcelog@host ~ $ touch ./test
marcelog@host ~ $ ./try.sh
waiting
waiting
waiting
done
It's not 100% safe. But I think it's worth giving it a try.
Hope it helps!
Upvotes: 2
Reputation: 311605
If you are running under Linux and the filesystem is local to your server, then you can use the inotify subsystem to wait until the file is closed and then trigger an action. The inotify-tools package includes the inotifywait program, which exposes inotify functionality to shell scripts.
For example, you can watch for the close_write
event in a directory like this:
inotifywait -e close_write -m /path/to/directory
With this command running, doing this:
echo hello > /path/to/directory/file
Will generate output like this:
/path/to/directory/ CLOSE_WRITE,CLOSE hello
So there you have the directory and filename that generated the event. In a shell script you can pipe this into a loop:
inotifywait -e close_write -m /path/to/directory | while read dir flags file; do
...do something with the file...
done
Upvotes: 3
Reputation: 52
you should check the modification time of the data and have a threshold on that. There is no other (easy) way to see if there is no more operation pending on the file.
so you should use
ls -l -t
in you find statement above and pipe that through a "sort" accordingly to you time threshhold.
Greetings
Upvotes: 0