我有一个脚本,它会遍历给定的目录,并自动压缩那些不包含至少一个在 30 天内使用过的文件的目录。现在,我想知道是否可以通过将 find 与 exec 一起使用来提高性能。我尝试了一些东西,但它不起作用。你有什么建议吗?
#!/bin/bash
# find all the directories
dirs=`find . -type d`
# iterate every file in every directory
for dir in $dirs
do
n="totar"
# search all the file in the directory
files=`find $dir -type f -atime -30`
for file in $files
do
n="keepasis"
done
if [ $n == "totar" ]; then
tar -zcvf $dir.tgz $dir
rm -r $dir
fi
done
我的想法是将第二个 for 循环替换为以下内容:
find $dir -type f -atime -30 -exec n="keepasis" {} \;
答案1
find
如果您在的操作中设置变量,-exec
则该变量将不可见。
找到文件并打印其名称这一事实find
足以决定您不想存档该目录。所以你不需要循环for file in $files
,而是检查它$files
不为空。
如果您的find
命令支持该-quit
操作,您可以使用它在第一个匹配后停止。 (看如何在第一次匹配后停止查找命令?)
不要将第一个的输出放入find
变量中并使用带有分词功能的 for 循环,您应该更好地逐行读取find
Lime 的输出。
#!/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
如果您使用的是 bash,您可以改进第一个find
以正确处理更多带有特殊字符的目录名称:find . -type d -print0 | while IFS= read -r -d '' dir; do
...
仍然存在一个性能问题:
如果目录的子目录中某处包含新文件,则不要将其删除。稍后您将获得包含此文件的所有子目录名称。在这种情况下,您将使用find
多次来查找相同的新文件。
我想到的唯一解决方案是使用两个find
,一些后处理和一个fgrep
:
- 让我们
find
打印所有新文件的名称,通过删除文件名、将所有父目录打印为单独的行、删除重复项并将列表放入文件 NEWDIRS 来处理输出。 - 第二次将
find
所有目录名称打印到第二个文件 ALLDIRS. - 用于
fgrep
查找 ALLDIRS 中与 NEWDIRS 中的行不匹配的所有行。
tar
在删除目录之前,您应该检查命令是否成功。