If you set a variable in find
's -exec
action this will not be visible.
The fact that find
has found a file and printed its name is sufficient to decide that you don't want to archive the directory. So you don't need the for file in $files
loop, instead check that $files
is not empty.
If your find
command supports the -quit
action you can use this to stop after the first match. (see How to stop the find command after first match?)
Instead of putting the output of the first find
into a variable and using a for loop with word splitting you should better read find
's output lime by line.
#!/bin/bash
# find all the directories
# -mindepth 1 prevents "find" from printing "."
find . -mindepth 1 -type d | while read -r dir
do
# a subdirectory might no longer exist if a parent has been archived before
if [ -d "$dir" ]
then
# search any new file in the directory
newfilefound=`find $dir -type f -atime -30 -print -quit`
if [ -z "$newfilefound" ]
then
tar -zcvf $dir.tgz $dir
rm -r $dir
fi
fi
done
If you are using bash you can improve the first find
to correctly handle more directory names with special characters: find . -type d -print0 | while IFS= read -r -d '' dir; do
...
There is still a performance issue:
If a directory contains a new file somewhere in a subdirectory you don't remove it. Later you will get all subdirectory names down to the one with this file. In this case you will use find
several times to find the same new file.
The only solution that comes to my mind is to use two find
, some post-processing and one fgrep
:
- Let one
find
print the names of all new files, process the output by removing the file names, printing all the parent directories as separate lines and removing duplicates and putting the list into a file NEWDIRS.
- With a second
find
print all directory names to a second file ALLDIRS.
- Use
fgrep
to find all lines from ALLDIRS that don't match a line in NEWDIRS.
You should check that the tar
command was successful before removing the directory.