shell编程之实现windows回收站功能分享

一. 功能简介
1. 将删除的文件放在回收站中
2. 恢复删除的文件
3. 实现linux rm命令的功能, 使用起来几乎和linux 系统自带的rm ,命令完全一样
4. 新增功能: rm -l, rm -e, rm -c
5. 该脚本每次在运行时候会检查$HOME/.trash 目录下文件大小之和, 若
超过最大容量, 脚本会自动将日志文件中所记录文件中的前一半文件从回
收站中清除,所以建议删除大文件(相对于回收站最大容量而言)直接用
命令/bin/rm 而不要用 rm.

二. 使用方法:
1. 将trash文件放到 $HOME/bin/
2. 在$HOME/.bashrc 文件中加入alias rm=”$HOME/bin/trash”, 重新登陆终端或执行bash命令。
3. 执行命令rm -e 配置回收站的最大容量,单位K
4. 回收站的默认目录为:$HOME/.trash, 默认配置文件为:$HOME/.trash/trash.conf
默认log文件为:$HOME/.trash/trash.log
5. 怎样恢复文件:
在linux 终端中输入rm -l, 然后 在RowNumber: 后面键入要删除文件所在的行标识:988 键入y/Y 然后按回车键 恢复成功.
如果想只查看删除列表, 则键入rm -l 后直接按回车键或者键入Q/q
6. 更详细的参数介绍请键入:rm --help

三. 注意事项
 1. 想要手动清空$HOME/.trash目录需要用/bin/rm命令, 请不要尝试用rm -r $HOME/.trash 的方法.
 2. 该脚本不支持rm -r -f , rm -rfi (选项组合超过2个)格式.
 3. 如果你可以你甚至可以用该脚本作为备份脚本, 假若想备份test2.txt你只需要执行rm test2.txt, 当然如果真想备份某个文件的话, 最好编写专门的备份脚本。

代码如下:

#!/bin/bash
#配置回收站最大的存储空间(字节)
#maxmemory=51200 (50M)
#maxmemory=102400 (100M)
#maxmemory=512000 (500M)

#根据情况设置为50M(对于isoa服务开发来说足够了)
maxmemory=3145728

#设置回收站所在的目录
trash=$HOME/.trash
#设置日志文件所在的目录
mvlog=$trash/trash.log

from1=$1
from2=$2

var_pwd=
var_father=

#回收站若不存在,则新建之
if [ ! -e $trash ];then
 mkdir -p $trash
 chmod 755 $trash
fi

#产生7位的随机数
function rand()
{
 a=(0 1 2 3 4 5 6 7 8 9 a b c d e A B C D E F)
 for ((i=0;i<7;i++))
 do
  echo -n ${a[$RANDOM%${#a[*]}]}
 done
}

random=$(rand)

#文件不存在时的提示信息
function file_null()
{
 local file=$1
 echo "rm: cannot remove '$file': No such file or directory"
}

#打印参数出错后的提示信息
function echo_msg()
{
 echo -n "rm: missing operand
Try 'rm --help' for more information.
"
}

function echo_msg2()
{
 echo -n "rm: invalid option  '$1'
Try 'rm --help' for more information.
"
}

#回收站管理函数
function deal()
{
 local tmp=$(mktemp /tmp/tfile.XXXXXX)
 local num=$(($(cat $mvlog| wc -l)/2))
 #awk -F: -v nu=$num  -v trash=$trash '{if (NR<=nu) system("rm -rf "trash"'/'"$2"':'"$3""); \
#else print $0}' $mvlog | sort -o $mvlog
 awk -F: -v nu=$num  -v trash=$trash '{if (NR<=nu) system("rm -rf "trash"'/'"$2"':'"$3""); \
else print $0}' $mvlog >> $tmp
 mv $tmp $mvlog
}

JUG=
#目录处理函数
function jug_cur()
{

local tmp=
 local dirname=$1
 local jug=${dirname/\/*/}
 if [ "$jug" == "." ];then
  var_pwd=${dirname/./$(pwd)}
JUG=0
 elif [ "$jug" == ".." ];then
  tm=$(pwd)
  tmp=${tm%/*}  
  var_father=${dirname/../$tmp}  
  JUG=1
#elif [ "$jug" == "~" ];then
#return 2
 else
JUG=2
 fi 
}

#命令不带参数时的普通文件删除函数
function rm1
{
 local filename=$(basename $from1)
 local dirname=$(dirname $from1)

jug_cur $dirname
 if [ "$JUG" -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ -d "$from1" ];then
  echo "rm: cannot remove '$from1': Is a directory"
 else
  if [ ! -e $from1 ];then
   file_null $from1
  else
   echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
   mv "$from1" "$trash/$filename:$random"
  fi
 fi
}

#rm -i
function rmi()
{
 local filename=$(basename $from2)
 local dirname=$(dirname $from2)

jug_cur $dirname
 if [ $JUG -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ -f "$from2" ];then
  echo -n "rm: remove regular file '$from2'?"
  read answer
  if [ "$answer" = 'y' -o "$answer" = 'Y' ];then
   echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
   mv "$from2" "$trash/$filename:$random"
  fi
 else
  if [ ! -e $from2 ];then
   file_null $from2
  else
   echo "rm: cannot remove '$from2': Is a directory"
  fi
 fi
}

#rm -f
function rmf()
{
 local filename=$(basename $from2)
 local dirname=$(dirname $from2)

jug_cur $dirname
 if [ $JUG -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ -f "$from2" ];then
  echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
  mv "$from2" "$trash/$filename:$random"
 else
  if [ ! -e $from2 ];then
   :
  else
   echo "rm: cannot remove '$from2': Is a directory"
  fi
 fi
}

#rm -r
function rmr()
{
 local filename=$(basename $from2)
 local dirname=$(dirname $from2)

jug_cur $dirname
 if [ $JUG -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ "$from2" = "." -o "$from2" = ".." ];then
  echo "rm: cannot remove directory: '$from2'"
 elif [ -e "$from2" ];then
  echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
  mv "$from2" "$trash/$filename:$random"
 else
  file_null $from2
 fi
}

#rm -rf
function rmrf()
{
 local filename=$(basename $from2)
 local dirname=$(dirname $from2)

jug_cur $dirname
 if [ $JUG -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ "$from2" = "." -o "$from2" = ".." ];then
  echo "rm: cannot remove directory: '$from2'"
 elif [ -e "$from2" ];then
  echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
  mv "$from2" "$trash/$filename:$random"
 else
  :
 fi
}

#rm -ir
function rmir()
{
 local filename=$(basename $from2)
 local dirname=$(dirname $from2)

jug_cur $dirname
 if [ $JUG -eq 0 ];then
  dirname=$var_pwd
 elif [ $JUG -eq 1 ];then
  dirname=$var_father
 fi

if [ -e "$from2" ];then
  if [ -d "$from2" ];then
   echo -n "rm: remove directory '$from2'?"
  else
   echo -n "rm: remove regular file '$from2'?"
  fi

read answer
  if [ "$answer" = 'y' -o "$answer" = 'Y' ];then
   echo "$dirname:$filename:$random:$(date +%Y-%m-%d.%T)" >> $mvlog
   mv "$from2" "$trash/$filename:$random"
  fi
 else
  if [ ! -e $from2 ];then
   file_null $from2
  fi
 fi

}

#清空回收站
function rmc()
{
 /bin/rm -rf $trash
}

function rml()
{
 local tmp=$(mktemp /tmp/tfile.XXXXXX)
 clear

if [ ! -d "$trash" ];then
  mkdir $trash
 fi

if [ ! -f "$mvlog" ];then
  touch $mvlog
 fi
 line=$(cat -n $mvlog | awk -F: '{print $1, "FileName:"$2, "Time: "$4":"$5":"$6}')
 linecount=$(cat $mvlog | wc -l)
 echo -e "$line"
 echo
 echo
 echo "[$linecount] Please enter the file you want to restore (replaced with the line number)"
 printf "RowNumber: "
 read answer
 if [ "$answer" = 'q' -o "$answer" = 'Q' -o "$answer" = "" ];then
  :
 else
  printf "Please confirm (Y/N): "
  read answer1
  if [ "$answer1" = 'y' -o "$answer1" = 'Y' ];then
   address=$(sed -n "$answer""p" $mvlog | awk -F: '{print $1}')
   filename=$(sed -n "$answer""p" $mvlog | awk -F: '{print $2}')
   filerand=$(sed -n "$answer""p" $mvlog | awk -F: '{print $3}')
   fullname=$address/$filename
   if [ -e "$fullname" ];then
    echo "The file exist!"
    sleep 0.5
   else
    old="$trash/$filename:$filerand"
    new="$address/$filename"
    mv "$old" "$new"
    #deline=$(cat $mvlog|sed "$answer""d" | sort -o $mvlog)
    deline=$(cat $mvlog|sed "$answer""d" >> $tmp)
    mv $tmp $mvlog
    echo "restore success!"
    sleep 0.5
   fi
  fi
 fi
}

function help()
{
 cat << 'EOF'
Usage: rm [OPTION]... FILE...
Remove (unlink) the FILE(s).

-f, --force   ignore nonexistent files, never prompt
-i, --interactive prompt before any removal
--no-preserve-root do not treat `/' specially (the default)
--preserve-root   fail to operate recursively on `/'
-r, -R, --recursive   remove directories and their contents recursively
--help display this help and exit

By default, rm does not remove directories.  Use the --recursive (-r or -R)
option to remove each listed directory, too, along with all of its contents.

To remove a file whose name starts with a `-', for example `-foo',
use one of these commands:
rm -- -foo

rm ./-foo

Note that if you use rm to remove a file, it is usually possible to recover
the contents of that file.  If you want more assurance that the contents are
truly unrecoverable, consider using shred.

Report bugs to <bug-coreutils@gnu.org>.
EOF
}

#脚本开始

#检测回收站已用存储空间,如果已经达到最大值,则删除日志文件中位于前面的一半的文件
mem=$(du -s $trash|awk '{print $1}')
if [ "$mem" -gt $maxmemory ];then
 deal
fi

if [ "$#" -eq 0 ];then
 echo_msg
fi

if [ "$#" -eq 1 ];then
 case "$from1" in
  -i)
  echo_msg

-f)
  echo_msg

-r | -R)
  echo_msg

-ir|-ri|-iR|-Ri|-if|-fi|-rf|-fr|-Rf|-fR)
  echo_msg

-l)
  rml

-c)
  rmc

--help)
  help

-*)
  echo_msg2 $from1

*)
  rm1

esac
fi

if [ "$#" -ge 2 ];then
 until  [ "$2" = "" ]
 do
  from2=$2
  case "$from1" in
   -i)
   rmi

-f)
   rmf

-r|-R)
   rmr

-l)
   rml

-rf|-Rf|-fr|-fR)
   rmrf

-ir|-ri|-iR|-Ri)
   rmir

-if|-fi)
   rmf

--help)
   help
   exit 1

-*)
   echo_msg2 $from1
   exit 1

*)
   {
    until [ "$1" = "" ]
    do
     from1=$1
     rm1
     shift
    done
   }

esac
  shift
 done
fi

exit

(0)

相关推荐

  • 让代码整洁、过程清晰的BASH Shell编程技巧

    这是我写BASH程序的招式.这里本没有什么新的内容,但是从我的经验来看,人们爱滥用BASH.他们忽略了计算机科学,而从他们的程序中创造的是"大泥球"(译注:指架构不清晰的软件系统). 在此我告诉你方法,以保护你的程序免于障碍,并保持代码的整洁. 一.不可改变的全局变量 1.尽量少用全局变量 2.以大写命名 3.只读声明 4.用全局变量来代替隐晦的$0,$1等 在我的程序中常使用的全局变量: 复制代码 代码如下: readonly PROGNAME=$(basename $0) read

  • 利用shell编程实现DOS风格的Linux命令行

    如果你是习惯于Windows命令提示符的IT人,当你第一次使用Linux命令行时,一定会感到无所适从.你所熟悉的DOS命令再Linux中基本不存在.摆在你面前的是一大堆要记背的命令. 一种替代方案是利用强大的Linux外壳命令编写shell脚本,让你在Linux下也能用DOS命令.下面告诉你怎么做. shell脚本编写基础    从定时备份到执行简单命令,Linux的shell脚本可以执行各种功能.几乎所有的程序都可以用shell脚本来运行.在脚本中甚至可以包含一些简单的条件选择.shell脚本

  • shell编程基础知识小结

    1.文件类型介绍linux系统中主要包括以下七种文件类型: d 目录 - 普通文件 l 符号链接 s 套接字文件 b 块设备文件 c 字符设备文件 p 命名管道文件 2.正则表达式正则表达式在shell编程中非常重要. 从一个文件或命令输出中抽取或过滤文本时.可使用正则表达式(RE),正则表达式是一些特殊或不很特殊的字符串模式的集合. 基本的元字符集:^ 只匹配行首.$ 只匹配行尾.* 一个单字符后紧跟*,匹配0个或多个此单字符.[] 匹配[]内字符,可以是一个单字符,也可以是字符序列.可以使用

  • Shell编程之Shell变量学习总结

    一.变量操作 A.变量显示.打印语法:echo $varB.变量设置语法:var=value 变量的设置规则:1.变量两端不能直接接空格符2.变量名称只能是因为字母与数字,但开头不能使数字3.双引号内的特殊字符如$等,保持原本特性 复制代码 代码如下: [root@bogon ~]# var="lang is $LANG"[root@bogon ~]# echo %varroot@bogon ~]# echo $varlang is zh_CN.UTF-8 1. 单引号内的特殊字符则仅

  • Shell编程指南

    基础知识 shell执行方式   sh xx.sh (文件须有r权限)  ||  ./xx.sh (文件须有x权限) 注:sh xx.sh方式比较安全 文件名后缀 .sh shell内容开头 #!/bin/bash || #!/bin/sh || #!/bin/csh || #!/bin/ksh 注:#!/bin/bash 使用比较多 退出  exit 0 变量赋值与使用 不需要定义即可直接使用  注:变量赋值时=号两端不能有空格 以$变量名或${变量名}访问变量内容 流程控制 判断  注:确保

  • 深入浅出Shell编程 Shell变量介绍

    •深入浅出Shell编程: Shell 变量 ◦1 系统变量 ◦2 Shell用户变量 ■2.1 基础 ■2.2 使用技巧 ■2.3 shell 中的数组 ◦3 shell 环境变量 先不要管Shell的版本,来看看Shell 变量,在Shell中有三种变量:系统变量,环境变量,用户变量.其中用户变量在编程过程中使用最多,系统变量在对参数判断和命令返回值判断会使用,环境变量主要是在程序运行的时候需要设置. 1 系统变量 Shell常用的系统变量并不多,但却十分有用,特别是在做一些参数检测的时候.

  • Shell编程的一些知识集合

    下午在写程序的时候需要将shell命令返回的数值赋予给某变量,使用了a=$()的方法 soft=$(grep -i "\(Software \)Token/Passcode/." 123.txt |wc -l) echo "[+] 软卡总数:" $soft ...... #!shell下的运算 over=$((var-use)) echo "[+] 剩余硬卡:" $over Shell的嵌入命令 : 空,永远返回为true . 从当前shell中

  • PowerShell编程中的一些命名规则参考

    本文介绍PowerShell自定义函数在使用时的最佳实践(Best Practices).包括函数名的命名.可选参数.必选参数等. PowerShell中的函数定义可以很简单的使用一个"function <函数名>{函数体}"的形式去定义.但微软推荐创建函数时遵循以下实践规则. 1.函数名. 使用cmdlet的统一命令规则,即"动词-名词"的形式.如Write-Host,表示输出到主机.如果是获取一个列表,不要使用List作为动词,建议使用Get,如Ge

  • shell编程基础之认识与学习BASH

    1.认识Bash 通过Shell将输入的指令与Kernel沟通,让Kernel控制硬件工作查看Shell:cat /etc/shell登录后预设的shell类型记录在/etc/passwd中,与账户相关命令别名:alias lm='ls -al' #注意有无空格帮助:man bash命令类型:type 复制代码 代码如下: type ls # ls is aliased to `ls –color=auto'type cat # cat is hashed (/bin/cat)type cd #

  • 分享shell编程中的几个小技巧

    1.打印一些头信息command  <<  dilimiter----dilimiter 以分界符号dilimiter中的内容作为命令的标准输入常用在echo命令中,这样就避免了没输出一行就要使用一个echo命令,同时,输出格式的调整也相应变得简单了.例如:  echo << something_message**********************hello, welcome to use my shell script **********************somet

  • shell编程基础 单引号和双引号的区别

    下面用一个简单的shell程序要说明一下. debian:~/learn/shell# cat phonebook Alice Chebba 973-555-2015 Barbara Swingle 201-555-9257 Liz Stachiw 212-555-2298 Susan Goldberg 201-555-7776 Susan Topple 212-555-4932 Tony Iannino 973-555-1295 Stromboli Pizza 973-555-9478 deb

  • shift妙用之解决shell编程中的入参问题

    我说过了,shell是我的常规武器,目前虽然还不纯熟,但是我爱shell这门语言,在Linux下面混,总要写脚本.程序员是有基因,对编程语言是有偏好的,你让我写C代码,我会觉得很爽,会有困难,会有痛苦的摸索和学习,但是,我愿意:学习shell/python,我也很乐意,甚至Lisp这种冷门的语言我也充满了好奇,虽然现在Go和Erlang我一点也不懂,但是我按耐不住对这两种语言的兴趣,只要我抽出手来,一定会和他们缠绵一番.有爱就会有恨,我痛苦地意识到到自己是个很情绪化的程序员,哪怕我一遍遍地骂自己

随机推荐