目前,我正在做完整的手工工作。
find /home/bash_cookbook/bash_cookbook/glassfish/domains/blog/logs -mtime +7 -type f -name 'application.log_*' -exec rm {} \;
仅输入我要遍历的所有目录名称就花了我 1 个小时。
问题?
有100多台服务器,每台服务器中有20个不同的域,每个域都有不同的域名称。我想到的一个聪明的方法是排除某些目录而不是包含所有目录。因为其中一些包含一些域,例如我不需要触及的“备份”。
但我不知道如何实现它。
我能想到的另一个巧妙的技巧是这个。
find /home/bash_cookbook/bash_cookbook/glassfish/domains/$domains_except_excluded_domains/logs -mtime +7 -type f -name 'application.log_*' -exec rm {} \;
为此,我需要domains_ except_excluded_domains 变量,该变量需要包含我想要排除的所有域。如何才能实现这一目标?
答案1
如果您正在使用bash
或其他支持数组的 shell,您可以列出要包含的域集以进行处理:
#!/bin/bash
incDomains=('blog' 'news' 'webmail' …)
for domain in "${incDomains[@]}"
do
echo "Considering $domain"
find "/home/bash_cookbook/bash_cookbook/glassfish/domains/$domain/logs" -mtime +7 -type f -name 'application.log_*' -delete
done
echo "Done"
我猜测$domain
变量应该插入到find
路径中的位置。根据需要移动它。
你可以使用类似的东西排除域(如果您确定能够安全地枚举它们)。此方法从要排除的域列表开始,将它们转换为关联数组(哈希)以进行快速查找,然后遍历域目录集,跳过哈希中的任何目录:
#!/bin/bash
excDomains=('blog' 'news' 'webmail' …)
declare -A excDomainsH
for domain in "${excDomains[@]}"; do excDomainsH[$domain]=1; done
for domainPath in "/home/bash_cookbook/bash_cookbook/glassfish/domains"/*
do
domain="${domainPath##*/}"
[[ "${excDomainsH[$domain]}" -eq 1 ]] && continue
echo "Considering $domain"
find "$domainPath/logs" -mtime +7 -type f -name 'application.log_*' -delete
done
echo "Done"
在这两种情况下我都会强烈推荐-delete
直到您-print
确定代码按预期工作为止。如果您的实现find
没有-delete
考虑使用-exec rm -f {} +
(请注意+
最后)
答案2
为了排除整个目录,一个选项是负面匹配路径:
find ! -path '*exclude1*' ! -path '*exclude2*' ...
与 相比-name
,-path
可以包含斜杠并且不会特殊对待斜杠。
如果您的主要问题是速度,原因可能不是搜索目录太多,而是每个文件-exec rm {}\;
调用一次。rm
只需将其替换为-delete
.另请阅读有关和man find
之间的区别 ,其中后者将使用尽可能多的结果作为命令参数列表。-exec command {}\;
-exec command {} +
答案3
这是我对这个问题的尝试。
脚本
#!/bin/bash
given_path=/home/techyman/glassfish4/glassfish/domains
excluded_folder=x
for each in $(ls $given_path); do
if [ "$excluded_folder" = "$each" ]; then
echo "This is x"
continue
else
echo "this is not x"
cd $given_path/$each/logs
echo "This is $PWD"
fi
done
它能做什么
- 这将转到给定的路径。
- ls 列出列表吗
- 如果 ls 等于排除的文件夹,它将使用 continue 语句跳过它
- 否则它会进入日志目录并执行一些操作。
更新:
#!/bin/bash
given_path=/home/techyman/glassfish4/glassfish/domains
excluded_folder=x
for each in "$given_path"/*; do
if [ "$excluded_folder" = "$each" ]; then
echo "This is x"
echo "$PWD"
continue
else
echo "this is not x"
echo "$PWD"
cd $each/logs
# echo "This is $PWD"
# echo "This is $x"
fi
done
更新
#!/bin/bash
given_path=/home/techyman/glassfish4/glassfish/domains
excluded_folder="x"
function clear_log() {
cd "$each"
echo "$PWD"
find . -mtime +"$1" -name "*.log" -exec rm -f {} \;
#echo "$2"
#echo "$1"
}
for each in "$given_path"/*; do
if [ "$each" = "$given_path/$excluded_folder" ]; then
echo "$each"
#echo "This is x"
#echo "Do nothing"
continue
else
#echo "this is not x"
#echo "$each"
#case statement goes here
case $each in
*a)
echo "This is a"
clear_log 7 "$each"
;;
*b)
echo "This is b"
clear_log 4 "$each"
;;
*c)
echo "This is c"
clear_log 5 "$each"
;;
*d)
echo "This is d"
clear_log 6 "$each"
;;
*e)
echo "This is e"
clear_log 8 "$each"
;;
esac
fi
done