Avatar of Lico_w
Lico_w
 asked on

BASH Scripting Check If a file is being Accessed

I need to use a find script to find files of a certain type then I would like to check if they are being accessed and if they are clear the contents otherwise remove the file. I'm ok with the find part but should I pipe the output to some kind of If statement.
Unix OSLinux OS Dev

Avatar of undefined
Last Comment
Lico_w

8/22/2022 - Mon
woolmilkporc

I  assume that this Q is releated to the other one requesting assistance on how to clear a file?

If so, and if you have the lsof utility at hand, you could do:

find ./ -name "*.log" -type f -mtime +1 | while read file ; do lsof $file >/dev/null || >$file; done

lsof returns a "false" returnconde if the file is not open, so we use "||" here.
 
wmp
Lico_w

ASKER
Ok I think I understand this, we are doing the find, piping it to the while loop, then we're checking if the file is open (lsof $file) then we are copying the contents of a null file to the current file (>/dev/null || >$file).

Please confirm and then I will award points.
woolmilkporc

That's quite correct , but "copying the contents of a null file ..." doesn't describe exactly what happens.

>$file just opens a file for output and closes it immediately afterwards, because there is no data to be written to it (as opposed to e.g. echo "This File is Empty!" >$file), thus effectively emptying it.

wmp
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Lico_w

ASKER
Just tested this and it doesn't work. I have logged on with another user and left the file open with vi. I've then logged on as myself and ran the script but it didn't clear the file?
woolmilkporc

vi does not keep the file open.

It is read into memory, that's all.
ckiral

Hi,

I assume that you want to clear contents of  open files only and then remove if found files are already closed.  

I suggest to write a  little script to make necessary tests on find command's output.
Try this one:
---
#!/bin/bash
#FileCleaner.sh
lsof $1 && > $1 && exit 0;
rm $1
exit 0
---
You can now use this script with your find command as follows:

find ./ -name "*.log" -type f -exec ./FileCleaner.sh '{}' \;

-
As woolmilkporc already mentioned; you can not test it with vi.
In one terminal you can type
cat  > testfile
(It will open a new file handler)
Then type some text in to it. In an  other terminal you should now see your text using command
cat testfile
After that try the find command  with testfile pattern
When command exit; you'll notice that the file is now empty as you requested...

--

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
woolmilkporc

Attention!

lsof returns "1" if the file is not open!

So you should use || instead of &&!

wmp
SOLUTION
ckiral

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
woolmilkporc

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ckiral

woolmilkporc; in my opininon your version will never evaluate closed file case...
The command will exit as soon as lsof will return false.

Please confirm...
ckiral

Please forget my last post about woolmilkporc's version, it will work as expected.
My mistake...
Your help has saved me hundreds of hours of internet surfing.
fblack61
Lico_w

ASKER
Apologies I've been away for a week, I'm going to test this now and award points for my outstanding questions. Is there a way I can keep a file open so that I can test this? Obviously as you stated you can't use vi but is there another option?
woolmilkporc

You could open a file (and empty it if it exists) with

cat > filename

or open an existing file without emptying it (but please be careful - do not destroy a file you need) with

cat >> filename

Terminate "cat" with <Ctrl><C>

wmp
Lico_w

ASKER
Many thanks for the comments, does exactly what I need it to do and I've also learned a lot!!
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Lico_w

ASKER
One final thing...if I wanted to rm the file i.e. if it ISN'T being accessed how would I do that? Is it just a simple modification on the above or should I post a new question?
woolmilkporc

That's what this thing is supposed to do:

find ./ -name "*.log" -type f -mtime +1 | while read file ; do lsof $file >/dev/null && >$file || rm $file; done

The && >$file part means "Empty it if it's being accessed" and the || rm $file part means: remove it if it's not being accessed.

To just remove files not being accessed without the "emptying" part modify like below:

find ./ -name "*.log" -type f -mtime +1 | while read file ; do lsof $file >/dev/null || rm $file; done

wmp



Lico_w

ASKER
I thought that was the case but seems I had a slight typo preventing the rm bit working, thanks again
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck