2

short story is, I probably need a simple loop in bash which checks periodically whether the size of a given file has changed or not since last checked.

Long story, I will be downloading a file my_file.txt using Firefox. I'd like to run a command after the download has completed. Firefox doesn't seem to provide dbus calls that I could make use of. There exist some add-ons with said feature but I need a rather reliable solution. So I thought I could run a bash script that periodically checks whether the size of my_file.txt is changing over time, or has settled. The file is a text file of size <=5mb and will be downloaded locally, so it is pretty reliable and the download should run linearly (no disconnections, server issues etc).

Could you help me write such simple bash script? The frequency of probing the file really seems to be key to make the thing work effectively. Like I said, it's a text file of <=5mb but can be as small as 10kb, residing on a SSD drive.

Also, maybe there are better ways to accomplish this? Like I say, I need a reliable solution that runs in Linux with minimal dependencies. Maybe a download manager? Or any file monitoring daemon? Or a filesystem API for this? Or use access time rather than size?

| improve this question | | | | |
  • 1
    Why Firefox and not a tool built for the job, like curl or wget? – jasonwryan May 4 '16 at 20:55
  • well I am building a notebook in html5 so will use firefox. not sure if I am able to download stuff like <a id="saveButton" target="iframe" download="note.txt" href="#" onclick="save();">Save</a> via an external handler like wget... this notebook is a nice thing btw, and the issue described is the last one left. – jabol240 May 4 '16 at 21:05
  • ...no server will be run, just a local html file opened in a browser. – jabol240 May 4 '16 at 21:13
1

If you just want to wait until the file is unchanged then something like

 size=0
 size2=$(stat --printf=%s $filename)
 while [ $size != $size2 ]
 do
   sleep 5
   size=$size2
   size2=$(stat --printf=%s $filename)
 done

If you're able to write some C then using the inotify(7) set of calls might help; you can trigger an action on a CLOSE event.

| improve this answer | | | | |
4

Assuming the only thing that has a file open is the program doing the downloading, the command

/usr/sbin/lsof path/to/your/file | wc -l

should return 2 if the file is still open, or 0 if nobody has it open.

Two because one line is a list of column labels, the second is the status line for the file.

When the download is complete, no one should have the file open.

You could use that result in your poll.

You need the full path to lsof because its usually an administrator command, so lives in /usr/sbin. It probably has options that only a superuser can use, but this isn't one of them.

| improve this answer | | | | |
  • Awesome. I've resorted to looping in the past. A quick scan through the man page shows lsof -t will produce terse output: it will show the pid that has the file, so pid=$(/usr/sbin/lsof -t filename); if [[ -n $pid ]]; then echo the file is open; fi – glenn jackman May 5 '16 at 15:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.