linux递归遍历并清理⽬录(2种⽅法)
⽅法⼀
shell脚本如下:
#!/bin/bash
#⽇志⽂件路径
logPath=/var/log/yx.log
echo -e "$(date +%Y%m%d" "%H:%M:%S): 清理程序开始执⾏!清理规则:A.⽂件⼤于100M,且存在时间超过5天;B.模型⽬录下的⼦⽬录存在时间超过30天
!\n"
echo -e "$(date +%Y%m%d" "%H:%M:%S): 清理程序开始执⾏!清理规则:A.⽂件⼤于100M,且存在时间超过5天;B.模型⽬录下的⼦⽬录存在时间超过30天!\n" >> $logPath
#计数器,计算总共删除了多少个⽬录
dirCnt=0
#计数器,计算总共删除了多少个⽂件
fileCnt=0
function recursive() {
#dir="$1"
#if [ "$dir" == "" ];then
#  echo 请输⼊⼀个参数,指定要清理的⽬录!
#else
#currDir=$1
#判断参数$1,是否以 / 结尾
#if [[ "$currDir" != */ ]];then
#  #echo 当前⽬录/⽂件:${1%%/}
#  currDir=$currDir"/"
#fi
echo -e "当前⽬录:$1"
echo -e "当前⽬录:$1" >>$logPath
#lines="`ls -l --time-style='+%Y%m%d' $1 | awk '{print $2,$6,$7,$1$8}'`"
#while循环位于管道中,这意味着在运⾏过程中,while循环实际是位于⼀个新的SHELL中的,while循环中的变量和⽂件开头定义的变量是两个不同的变量,所以while循环中所改变的值在while循环结束后⽆法保存下来。解决这个问题的⽅法就是不    while read line
do
#echo $line
#oldIFS=$IFS
#IFS=" "  #设置字符串的分隔符为空格,默认为空格,所以这⾥不需要设置
arr=($line)
#echo "  ${#arr[@]}  ${arr[@]}"
if [[ "${arr[0]:0:1}" == "d" ]];then
#⽂件创建/修改⽇期距离当前⽇期的天数
diffDays=$((($(date +%s) - $(date +%s -d ${arr[2]}))/86400))
#判断当前⽬录是否是模型⽬录下的⼦⽬录,⽐如/data/xwd/20191102/,且存在时间超过30天,超过则删除
if [[ "${arr[3]}" =~ ^[0-9]{4}(0[0-9]|1[12])([012][0-9]|3[01])$ && $diffDays -gt 30 ]];then
rm -rf $1/${arr[3]}
echo "    $1/${arr[3]}:该⽬录存在时间超过30天,删除之"
echo "    $1/${arr[3]}:该⽬录存在时间超过30天,删除之" >> $logPath
let dirCnt++
#否则,递归处理下⼀个⽬录
else
if [[ "$1" != */ ]];then
recursive $1/${arr[3]}
else
recursive $1${arr[3]}
fi
fi
elif [[ "${arr[0]:0:1}" == "-"  ]];then
#echo "    $1/${arr[3]}"
#如果⽂件存在天数⼤于60天,则删除(该条规则⽬前作废)
#if [ $diffDays -gt 60 ];then
#  echo "    $1/${arr[3]}:该⽂件存在时间超过60天,删除之"
#  rm -f $1/${arr[3]}
#  let fileCnt++
#⽂件创建/修改⽇期距离当前⽇期的天数
diffDays=$((($(date +%s) - $(date +%s -d ${arr[2]}))/86400))
#如果⽂件⼤于100M(104857600字节),且存在时间超过5天,则删除
if [[ ${arr[1]} -gt 104857600 && $diffDays -gt 5 ]];then
rm -f $1/${arr[3]}
echo "    $1/${arr[3]}:该⽂件⼤于100M,且存在时间超过5天,删除之"
echo "    $1/${arr[3]}:该⽂件⼤于100M,且存在时间超过5天,删除之" >> $logPath
let fileCnt++
fi
fi
done <<< "`ls -l --time-style='+%Y%m%d' $1 | awk '{print $1,$5,$6,$7}'`"
#fi
}
if [[ "$1" == "" ]];then
echo -e "请输⼊⼀个参数,指定要清理的⽬录!\n"
echo -e "请输⼊⼀个参数,指定要清理的⽬录!\n" >> $logPath
exit 1
else
recursive $1
fi
if [[ $dirCnt -eq 0 && $fileCnt -eq 0 ]];then
echo -e "\n$(date +%Y%m%d" "%H:%M:%S): 清理程序执⾏完毕!没有要删除的⽂件!\n"
echo -e "\n$(date +%Y%m%d" "%H:%M:%S): 清理程序执⾏完毕!没有要删除的⽂件!\n" >> $logPath
else
echo -e "\n$(date +%Y%m%d" "%H:%M:%S): 清理程序执⾏完毕!共删除了 ${dirCnt} 个⽬录,和 ${fileCnt} 个⽂件!\n"
echo -e "\n$(date +%Y%m%d" "%H:%M:%S): 清理程序执⾏完毕!共删除了 ${dirCnt} 个⽬录,和 ${fileCnt} 个⽂件!\n" >> $logPath
fi
exit
⽅法⼆
#还未全部测试
#删除⼤于100M,且超过5天的⽂件
find . -size +100M -mtime +5 -type f -exec ls -alh {} \ >> yx.log;
find . -size +100M -mtime +5 -type f -exec rm -rf {} \;
#删除超过30天的⽂件夹
find /data -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec ls -ahl15 {} \;
find /data -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec rm -rf {} \;
⼀、过程中涉及的知识:
1、
查看当前⽬录的总⼤⼩
sudo du -sh .
查看当前⽬录下的所有⼦⽬录和⼦⽂件的总⼤⼩
sudo du -sh *
查看指定⽬录的总⼤⼩
sudo du -sh data/
2、普通的shell脚本使⽤以下语句作为第⼀⾏:
/bin/bash
3、修改⽂件/⽂件夹的修改时间:
touch -mt 1901020905 file1
4、ls 查看格式化后的时间:
ll --time-style='+%Y%m%d %H:%M:%S'
-rw-r----- 1 weblogic weblogic 5557932 20190102 09:05:
5、⽇期的格式化:
特定⽇期转化为时间戳,即距离1970.01.01 08:00的秒数:
linux查看当前路径命令$(date +%s -d '20120101') #结果为:1325347200
当天和指定⽇期之间相隔的天数:
diffDays=$((($(date +%s) - $(date +%s -d '20120101'))/86400))
格式化当前⽇期:
echo $(date +%Y%m%d" "%H:%M:%S) #结果是:20191205 13:56:24
6、单、双括号运算符:
shell单括号运算符号:
a=$(date);
等同于:a=date;
双括号运算符:
a=$((1+2));
echo $a;
等同于:
a=expr 1 + 2
7、awk知识:
在awk中,输⼊⽂本的每⼀⾏中,由域分隔符分开的每⼀项称为⼀个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。awk⼯作流程是这样的:读⼊有'\n'换⾏符分割的⼀条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表⽰所有域,$1表⽰第⼀个域,$n表⽰第n个域。
-F ':' 指定输⼊值的域分隔符(field-separator)为英⽂冒号 :
eg. ls -l --time-style='+%Y%m%d' $1 | awk '{print $1,$5,$6,$7}'
在ls -l列出的⽂件列表信息中,打印第1、5、6、7个域
8、echo命令: -e 开启转义
eg. echo -e "请输⼊⼀个参数,指定要清理的⽬录!\n"
注: \n 表⽰换⾏符。
9、数组:
echo ${#arr[@]} #打印数组包含元素的个数
echo ${arr[@]} #打印数组的所有元素
echo ${arr[0]:0:1} #数组中某个元素从索引0开始截取1个字符,然后打印
shell 字符串转换为数组:
line="a,b,c"
oldIFS=$IFS
IFS=, #设置字符串的分隔符为英⽂逗号,不设置的话默认为空格
arr=($line)
10、shell中不能使⽤别名,如ll等。
11、vim中全局替换,其中包含了转义符号 \ :
:%s//var/log/yx.log/$logPath/g
⼆、过程中出现的错误:
1、Shell脚本报错:
/usr/local/bin/cleanData.sh: line 32: [: ==: unary operator expected
原因:在匹配字符串时⽤了类似这样的语句:
if[ $timeofday = "yes" ] ...
如果变量timeofday的值为空,那么就if语句就变成了if [ = "yes" ],这不是⼀个合法的条件。为了避免出现这种情况,我们必须给变量加上引号if [ "$timeofdat" = "yes" ],这样即使是空变量也提供了合法的测试条件,if [ " " = "yes" ]
2、Shell脚本报错:
cleanData.sh: line 63: [: missing `]'
其中,63⾏代码为:if [ ${arr[1]} -gt 104857600 && $diffDays -gt 7 ];then
原因:if使⽤了单个括号,需要使⽤双括号。
⼩结:⽹上还有⼀个错误原因是if ["$NGINX_FLAG" = '1'],"$NGINX_FLAG"之前和'1'之后没有空格,两个都要有空格。
另外,字符串的if语句⽐较最好使⽤双括号。他⽀持字符串的模式匹配,使⽤=~操作符时甚⾄⽀持shell的正则表达式。字符串⽐较时可以把右边的作为⼀个模式,⽽不仅仅是⼀个字符串,⽐如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。