打造Linux 回收站

作者: admin 分类: Linux,Shell脚本 发布时间: 2022-08-01 14:31 浏览:8,467 次    

Linux默认没有回收站,使用rm命令会直接从系统中删除,可能会造成误删,恢复困难,因此仿照windows回收站使用shell脚本实现类似功能。

#!/bin/bash

###################################################################
# File Name: Recycle.sh
# Author: xunyin
# E-mail: lnhxzwb@126.com
# Created Time: 2022年 08月 01日
#==================================================================
#声明:本程序基于CENTOS7.X系统测试,其它系统请测试后使用
#      默认保留回收站数据15天
###################################################################

cat > /bin/del << 'END'
#!/bin/bash

#帮助信息 
rm_help()
{
cat << EOF
=======================<使用方法>======================
    删除文件:   rm file1 [file2 file3...]
    查看回收站: rm -l
    清空回收站: rm -d     (永久删除,不可恢复)
    查看帮助:   rm -h
    撤销删除:   unrm     (撤销最近一次删除)
======================================================
EOF
exit 1
}

#查看回收站
rm_list()
{
/bin/ls --color=auto ${rm_dir}
exit 1
}

#清空回收站
rm_clear()
{
read -p "回收站文件将永久删除,是否继续(Y|N):" next
    case $next in
            Y|y)
            /bin/rm -rf ${rm_dir}
            ;;
            N|n)
            echo "操作已取消"
	    exit 1
            ;;
            *)
	    echo
            echo "==================================================="
            echo "输入有误!请输入 Y|y 清空回收站.输入 N|n 操作取消"
    esac
exit 1
}

#删除文件
rm_file()
{
rm_path=/tmp/rm_tmp.txt
echo ${opt_file} >${rm_path}
#tr " " '\n' <${rm_path} &>/dev/null
   for file in $(cat ${rm_path})
    do
    opt=^-.
    # 防止使用-rf等参数报错  
      if [ "$file" = "-f" ];then
        sed -i '/-f/d' ${rm_path}
        continue
     elif [ "$file" = "-r" ];then
        sed -i '/-r/d' ${rm_path}
        continue
      elif [ "$file" = "-fr" ];then
        sed -i '/-fr/d' ${rm_path} 
        continue
      elif [ "$file" = "-rf" ];then 
        sed -i '/-rf/d' ${rm_path}
        continue
      elif [ "$file" = "-l" ];then
	rm_list
      elif [ "$file" = "-d" ];then
	rm_clear
      elif [ "$file" = "/Recycle" ];then
	 rm_clear
      elif [ "$file" = "-h" ];then
	 rm_help
      elif [[ $file =~ $opt ]];then
         echo "$file 参数不正确,请检查!"
         exit 1
	 
	#防止执行 rm -rf /*	危险操作
      elif [ "$file" = "/bin" ]||[ "$file" = "/boot" ]|| \
           [ "$file" = "/dev" ]||[ "$file" = "/etc" ]|| \
           [ "$file" = "/home" ]||[ "$file" = "/lib" ]|| \
           [ "$file" = "/lib64" ]||[ "$file" = "/media" ]|| \
           [ "$file" = "/mnt" ]||[ "$file" = "/opt" ]|| \
           [ "$file" = "/proc" ]||[ "$file" = "/root" ]|| \
           [ "$file" = "/run" ]||[ "$file" = "/sbin" ]|| \
           [ "$file" = "/srv" ]||[ "$file" = "/tmp" ]|| \
           [ "$file" = "/sys" ]||[ "$file" = "/usr" ]|| \
           [ "$file" = "/var" ];then
           echo -e "\033[5;41;33m 警告:当前操作会损坏当前系统环境,禁止此危险操作!!!\033[0m " && exit 1
      else
    #防止回收站中出现同名文件报错	  
        now=$(date +%Y%m%d%H%M%S)
        file_path=$(dirname ${file})
        file_name=$(basename ${file})
		unrm_path=$(realpath $file)
	    cd ${file_path} 
        if [ ! -e $file ];then
            echo "$file 文件或目录不存在!"
            continue
         else
            echo -e "${unrm_path}:${file_name}_RM_${now}" >>/tmp/un_rm.db
            /bin/mv -f ${file_name} ${rm_dir}/${file_name}_RM_${now} &>/dev/null
            if [ $? -eq 0 ];then
               echo "${file_name} 已被删除!"
            fi
         fi
      fi 
done
cd /tmp
cat un_rm.db > unrm.db 2>/dev/null
> un_rm.db
/bin/rm -rf ${rm_path}

}

opt_file=$@
if [ $# -eq 0 ];then
rm_help
else
rm_dir=/.Recycle
#检查回收站目录是否存在
if [ ! -d ${rm_dir} ];then
mkdir -m 755 -p ${rm_dir}
rm_file
else
rm_file
fi
fi

END

#保留15天数据
cat >/var/spool/cron/rm_clear.sh <<EFF
rm_15 ()
{
find /.Recycle/ -mtime +15 -name "*_RM_*" | xargs /bin/rm -rf
#find /.Recycle/ -mtime +15 -name "*_RM_*" -delete
}
rm_15
EFF

cat > /bin/unrm << 'ENM'
#!/bin/bash
#帮助信息 
unrm_help()
{
cat << EF
=======================<使用方法>======================
    删除文件:   rm file1 [file2 file3...]
    查看回收站: rm -l
    清空回收站: rm -d     (永久删除,不可恢复)
    查看帮助:   rm -h
    撤销删除:   unrm     (撤销最近一次删除)
======================================================
EF
exit 1
}

#撤销删除
unrm_file()
{
for i in $(cat /tmp/unrm.db)
  do
    rm_name=$(echo $i | awk -F: '{print $2}')
    new_name=$(echo $i |  awk -F: '{print $1}')
    cd /.Recycle
    ls ${rm_name} &>/dev/null
    if [ $? -eq 0 ];then
       /bin/mv -f ${rm_name} ${new_name} 
    else
       echo "${new_name}文件或目录不存在!"
       continue
    fi
done
> /tmp/unrm.db
}

if [ $# -eq 0 ];then
   unrm_file
else
   echo "输入参数有误!"
   unrm_help
fi
ENM

chmod +x /bin/del
chmod +x /bin/unrm
sed -i "/rm=/d" /etc/bashrc
echo "alias rm='/bin/del'" >>/etc/bashrc
source /etc/bashrc
if [ $? = 0 ];then
echo "回收站设置成功!"  
sed -i '/clear/d' /var/spool/cron/root &>/dev/null
echo -e "#clear_recycle_15 \n59 23 * * *  sh /var/spool/cron/rm_clear.sh" >>/var/spool/cron/root 
echo "------------------------------------"
echo "请使用rm -h 查看使用方法"
else
echo "回收站配置失败,请使用 sh -x Recycle.sh 排查!"
fi
  • 注:请使用 source Recycle.sh 或 . ./Recycle.sh(注意两点之间有空格,source与点方式是等效的) 方式执行脚本,如果使用其他方式(./Recycle.sh,sh Recycle.sh,bash Recycle.sh)执行脚本,请手动执行 source /etc/bashrc 或使用bash使别名配置生效,否则当前终端别名无法使用(原因请见知识点)。
  • 知识点:使用加权限./,sh , bash执行脚本时,当前终端所在的shell 会fork一个子shell执行脚本,当执行完后再返回终端所在的shell。脚本中设置在fork出来的这个子shell(后续重新开启的新终端)中生效,子shell只能继承父shell的环境变量,而不能修改父shell的环境变量,所以脚本运行结束后,父进程的环境就会覆盖回去;而使用sorcue 或者.(dot) 会明确告诉shell不要fork执行脚本,而是在当前的shell执行,这样环境变量就可以保存下来,当前终端也会生效。
  • 查看使用方法 (rm -h)
%title插图%num
  • 删除文件(rm file1 [file2 file3])
%title插图%num
  • 查看回收站信息 (rm -l)
%title插图%num


温馨提示:如无特殊说明,本站文章均为作者原创,转载时请注明出处及相应链接!

发表评论