I have several cron tasks, each of which leaves a separate log file. Successful tasks generate no output, so I'm getting a lot of empty logs.
I'd like to clean it up automatically every day. Requesting find
to look for size=0 is easy, however I'd like to be sure I'm not removing a log that has been just created by a running task but not closed yet.
Is there a way to tell find
to skip open files, or I need to resort to lsof
?
According to my knowledge there is no straightforward way to do it with find.
Solution One
Generate a list of open files in the target folder
lsof.lst
. and generate the find list of that folder. then display files in thefind.lst
that are not in thelsof.lst
list.to generate the lsof.lst use the following command:
and then the following command to show the files not currently open in the same folder:
Solution Two
You could also do it in one go like this:
Explanation
Now i will try to explain the command so that you can improve it or change it or use the several command line tools in the future.
find folderName
will generate a list of all files in that folder and subfolders. the output of the find command is piped togrep
that is here being used with the-v
switch to exclude the items mentioned in the-E
parameters from the piped output of the find command. The result will be the output offind
minus the items mentioned in the-E
parameter.The trick here is to generate the list of open files and put it in the format that
grep -v -E
expects and can work with. grep -E takes a list of strings separated by '|'.lsof +D FolderName
will generate the list of open files in that folder, but the list includes a header, and many columns, one of which is the filename, and it could contain duplicates. So we useawk '{ if(NR>1)print $9 }'
to do two things, remove the first line withif(NR>1)
and print only the column containing the filename which is withprint $9
. The result is a list of filenames of the open files in that folder without the header.To remove duplicates, the output is piped to
sort
and thenuniq
, and the next commandawk '{print $0}' ORS='|'
turns the list into a sentence separated by '|', and the last command remove the last '|' as it is excessive.enclosing that command with the backquotes '
' executes that command in that spot and feeds the output to the
grep -v -E` command.