任务 2 编写Shell脚本实现回收站效果
任务目的
编写Shell脚本rm.sh
,实现回收站效果。具体效果为:调用rm.sh
删除文件时,先判断文件大小。删除小文件时直接把文件放在相同目录的隐藏回收站中,并自动设置计划任务,超过时间阈值后(7天)自动删除。删除大文件(超过1024M)则提示用户文件过大,询问是否永久删除,如果永久删除则调用rm
删除,如果不永久删除,则按照小文件的处理方法,同样放进回收站,延期自动清理。
任务步骤
1.建立测试目录
建立测试目录/test
,用作Shell脚本初稿的编写,以及后续测试文件的存放。
mkdir /test
cd /test
2.创建脚本文件
建立Shell脚本文件rm.sh
,编写Shell脚本的基本格式。
vim rm.sh
i
#!/bin/bash
按ESC键
:w
3.编写基本循环体
Linux系统的rm
命令有同时删除多个文件的用法,例如rm file1 file2 file3
,需要对多个文件一一操作。因此rm.sh
脚本整体为循环语句,对后面的各个文件(用预定义变量$*
表示)依次处理。此处使用for
循环即可。在Shell脚本中添加以下循环体:
for FILE in $*
do
done
其中FILE
为自定义变量,$*
表示执行该文件时后面附带的所有参数(即要删除的各个文件的文件名)。do
和done
之间为循环体,FILE
每取一个$*
的值,就进行一次循环,循环到$*
的最后一个文件后,自动终止循环。
4.进行文件判断
判断文件是否存在,如指定文件不存在则跳过该文件,进入下一个文件的循环。在Shell脚本中添加以下if
判断语句:
if [ ! -w $FILE ];then
echo "Warning: File [$FILE] not exists.Skip this file."
continue
fi
此处-w
表示:只有后面的文件确实存在,且当前用户具备写权限,才会判断为“真”(如果没有写权限也就不能删除)。如果满足则返回1,如不满足,则提示文件不存在或不能删,跳过这个文件。
5.确定回收站目录位置
设置回收站隐藏目录的位置,用自定义变量RECYCLEBINDIR
表示,此处参照Windows、HDFS等常用回收站的做法,将回收站目录放在被删文件的同一分区路径下,避免跨硬盘分区移动文件的效率问题。在Shell脚本中添加以下if
判断语句:
if [ "`dirname "$FILE"`" = '.' ];then
RECYCLEBINDIR="`pwd`/.RECYCLEBIN"
elif [ "`dirname "$FILE"`" = '/' ];then
RECYCLEBINDIR="/.RECYCLEBIN"
else
RECYCLEBINDIR="`dirname "$FILE"`/.RECYCLEBIN"
fi
此处考虑到用户删除文件时,可能使用绝对路径(如/test/123.txt
)或相对路径(如abc.txt
或data/abc.txt
),格式有差别,需要分情况处理。分别使用basename
和dirname
命令获取文件名和文件所在的目录,拼接出文件的绝对路径,在路径下放置一个.RECYCLE
目录即可,以.
(点)开头表示隐藏文件,将回收站目录隐藏起来。
6.新建回收站目录
新建回收站目录,并设置回收站权限为所有人可用。在Shell脚本中添加以下语句:
mkdir -p $RECYCLEBINDIR 2>/dev/null
if [ $? -ne 0 ];then
echo "Permission denied.Can't delete file [$FILE]. Skip this file."
continue
fi
chmod 777 $RECYCLEBINDIR
其中mkdir -p
命令表示新建目录,如果该目录已存在,则直接使用已存在的目录即可。但如果用户对当前目录没有权限,无法新建(没有写权限,也就不能再进行后面的删除),此时不进行报错(使用2>/dev/null
将报错直接丢弃)。使用if
语句判断,一旦返回值非0(表示上一条新建目录命令未成功),则提示权限不足,跳过本轮循环,进入下一个文件的处理。
7.编写删除文件函数
删除分成“放入回收站”和“彻底删除”两种,分别对应大文件和小文件的删除。使用函数实现,便于后面的重复调用,增加代码的模块化和可读性。在Shell脚本中添加以下语句:
function MoveFileToRecyclebin()
{
mv $FILE ""$RECYCLEBINDIR"/`basename $FILE`.`date +%Y-%m-%d-%H-%M-%S`"
at now+7day <<< "/usr/bin/rm -rf ""$RECYCLEBINDIR"/`basename $FILE`.`date +%Y-%m-%d-%H-%M-%S`"">/dev/null 2>/dev/null
}
function RemoveFileForever()
{
/usr/bin/rm -rf $FILE
}
其中MoveFileToRecyclebin()
函数表示移动文件到回收站,其中回收站目录已经在上文中赋值给RECYCLEBINDIR
目录。直接使用mv
命令把文件移动进去即可。针对连续删除多个同名文件的情况,mv
同时进行重命名,在文件后添加date +%Y-%m-%d-%H-%M-%S
格式的时间作为文件后缀,避免重名文件的冲突,也便于后续按时间查找被删除的对象。删除文件后,调用at
创建计划任务,通过<<<
直接将命令重定向给at
作为计划任务的内容,7天后使用rm
命令自动删除这个文件,释放空间。创建计划任务会在命令行产生反馈信息,用>/dev/null 2>/dev/null
直接丢弃反馈信息,不需要显示。
RemoveFileForever()
函数则直接调用系统rm
命令进行文件删除,释放空间。此处rm
命令使用全路径/usr/bin/rm
。主要用于删除大文件,给用户警告和提示,是否不经回收站直接删掉(Windows中也有类似的大文件提示机制)。
8.对文件进行删除处理
在Shell脚本中添加以下语句:
SIZE=`du -ms $FILE | awk '{print $1}'`
if [ "$SIZE" -gt "1024" ];then
echo "Warning: File $FILE is too large("$SIZE"M),delete it forever? y/n"
while read answer
do
if [ "$answer" == "y" ];then
RemoveFileForever
break
elif [ "$answer" == "n" ];then
MoveFileToRecyclebin
break
else
echo "Please input y or n"
fi
done
else
MoveFileToRecyclebin
fi
主要逻辑为:使用du -ms
判断文件大小。-ms
获取文件或目录的总大小,以MB为单位,去掉后面的其他信息,把单纯的数值赋值给自定义变量SIZE
。
对SIZE
的大小进行判断,超过1024MB则询问是否不经过回收站彻底删除,使用read
函数获取用户的键盘输入内容,赋值给自定义变量answer
进行判断。删除文件属于敏感操作,因此设置循环,如果用户输入不是y
或n
,就一直询问用户,直到用户输入y
或n
为时才执行删除操作(输入y
则调用RemoveFileForever
函数彻底删除,输入n
则调用MoveFileToRecyclebin
移动至回收站),并break
跳出循环。
如果文件不大于1024M,不需要询问,直接调用MoveFileToRecyclebin
函数移动至回收站。
9.保存文件
以上内容编写完毕后,保存文件并退出。
按ESC回到普通模式
:
wq
学员评价