写了个Linux 回收站脚本,妈妈再也不用担心我的用户主目录了
嘛,写了将近5 个小时,一个没效率的晚上终于给写完了。
嘛,真爽快~
3 年前当root 敢死队的时候rm 了一次根分区,脱队之后又rm 了一次主目录,那之后就写了几个防手滑的C 程序。
不过前几天Slackware 换Archlinux 的时候弄2 了,没备份就mkfs 了,只要用得着什么再重新写什么。
这套脚本感觉做的比那套C 语言中rm 替代指令要好一点。
全彩显示,支持正则表达式搜索,自己感觉健壮性也不是那么不堪一击。
这代码是一边看着《龙与虎》一边大半夜敲的,估计得有点bug,以后发现了再说吧~
话说很久没看到这么喜欢的纯爱番了,大爱逢坂大河~~~~~
最后就像-h 中说的一样,
只是为了自己用的舒坦
Over~
---------已知BUG:--------
1. irm_ 无法在不加路径的情况下删除连字符开头的文件,因为irm_ 没有像传统unix 程序一样的-- 开关
已经修复:现在你不但可以在此类文件名前加路径(例如"./"),也可以使用-- 开关来把-- 后来的参数一律不当作开关处理了。
详情请看irm_ -h。
2. 在一秒中之内删除两个相同文件名的文件时,irm_ 会询问是否覆盖,因为irm_ 的日期只精确到了一秒
已经修复:现在你可以尽情的在极短的时间内删除相同文件名的文件了,你几乎不可能遇到询问覆盖的情况,概率极小。
3. iunrm_ 在清空回收站的时候会忽略隐藏文件
已经修复:现在除了"."、".." 和".recycle_data",其他的都杀无赦。
4. irm_ 当删除一个带斜杠结尾的、不带路径的目录时(irm_ dir/),文件名不会被正确赋值。
已经修复:现在事先去除了可能导致问题的尾部反斜杠。
依旧是先上代码再上图喵了个咪的:
#!/usr/bin/perl # 程序连同iunrm_ 提供了一个简单的回收站机制 # 用来代替系统的rm 指令. # 珍爱膝盖,以防中箭,爱生活,爱/dev/sda ;) # # PS 扔到/usr/bin/irm_ # By: iSpeller use warnings; use strict; use 5.010; our $recycle = "$ENV{HOME}/.recycle/"; our $data_file = "$recycle".".recycle_data"; our @to_write; # 将要写入$data_file 的条目 # 冒牌的主函数,主要做一些irm_ ()之前的检查和irm_ ()的参数构造 MAIN: { # 只嫁Linux die "!!ERROR: Only run on GNU/Linux!\n\t" unless $^O =~ /^linux$/i; # 没有回收站目录先mkdir 一个 say "\033[0;31m !!WARN: \033[1;37mDirection ", "[\e[1;31m$recycle\033[1;37m] ", "dose not exsit, create it!\033[0;37m" and qx/mkdir $recycle/ unless -e -d $recycle; say "\033[0;31m !!WARN: \033[1;37mData file ", "[\e[1;31m$data_file\033[1;37m]", "dose not exsit, create it!\033[0;37m" and qx/touch $data_file/ unless -e $data_file; print_help () if (0 == @ARGV or $ARGV[0] =~ /-h/i); # 构造irm_ () 的参数并且调用之 my $argv = (join " ", @ARGV); my @irm__args; push @irm__args, $argv =~ /-.*f/ ? "use_force" : "no_force"; irm_ (@irm__args); exit 0; } # sub irm_ ($flag_force) # @flag_force = qs=w/use_force no_force/ # 处理参数和删除一条龙服务 my $no_switch = 0; sub irm_ { # 参数保留,文件换成新文件名然后调用系统指令mv my (@new_name, @old_name); # 处理参数 my $force = (shift @_) =~ /^use/ ? 1 : 0; # 只关心f 参数 for (@ARGV) { my ($file_name, $file_path); my $date = get_date (); # 不处理f 参数 next if (/^-\w*f\w*/); # 处理-- 参数但是只处理第一个 if (!$no_switch and /^--$/) { $no_switch = 1; say "\033[0;31m !!WARN: \033[1;32m", "Will not treat arg as switch now.\033[0;37m"; next; } # 不处理其他参数、"/"、"/*"和用户指令程序 # 如果-- 开关打开,那么将"-"开头的参数对待为文件名 say "\033[0;31m !!WARN: \033[1;37mIgnore arg ", "[\e[1;31m$_\033[1;37m]\033[0;37m" and next if (m{^/([^/]+)?$} or m{^/usr/bin.*$} or (m{^-.*$} and !$no_switch)); s{/?$}{}; # 去掉最后可能的/ if (m{/}) { # 是完整路径 m{(.*/)(.+)$} and ($file_path, $file_name) = ($1, $2); } else { # 是不带路径的文件名 ($file_path, $file_name) = ("", $_); } # 还要处理一下路径和文件名 $file_name =~ s{/$}{}; # 最后的斜杠可能造成困扰,如果有就除去掉 $file_path = $ENV{PWD}.'/'.$file_path if (m{^[^/]}); # 相对路径补全为绝对路径 # 构造mv 指令的两个参数 # 新文件名 = 旧文件名+"@"+$date+"_%RAND%_"+随机数 my ($new_name, $old_name) = ( "\"".$recycle.$file_name."@".$date."_%RAND%_".int (rand 1000)."\"", "\"".$file_path.$file_name."\""); push @new_name, $new_name; push @old_name, $old_name; } # mv 文件到$recycle for my $new_name (@new_name) { my $old_name = shift @old_name; my $cmd = sprintf "mv %s %s %s", $force ? "-f" : "-i", $old_name, $new_name; my $test_name = $old_name; $test_name =~ s/"$//g and $test_name =~ s/^"//g; if (-e $test_name) { say sprintf "\033[1;31m> \033[1;32m process %s \033[1;37m %s\033[0;37m", $force ? "force" : "", $old_name; qx/$cmd/; profile_add ($new_name, $old_name); } else { say "\033[0;31m !!WARN: \033[1;37mFile ", "[\e[1;31m$old_name\033[1;37m] dose not exsit!"; } } write_profile (); } # sub profile_add # 构造@to_write sub profile_add { my ($new_name, $old_name) = (shift @_, shift @_); push @to_write, (join "_\%MOVE_TO\%_", ($new_name, $old_name)); } # sub write_profile # 将@to_write 写入$data_file sub write_profile { open (FILE, ">>$data_file") or die "!!DIE: Can not read file [$data_file]!"; say FILE for (@to_write); close FILE; } # sub get_date # 返回时间字符串格式:年-月-日-时:分:秒 sub get_date { my ($sec, $min, $hour, $mday, $mon, $year_off) = localtime; my $date = sprintf "%s-%s-%s-%s:%s:%s", $year_off + 1900, be_two (++$mon), be_two ($mday), be_two ($hour), be_two ($min), be_two ($sec); return $date; } # sub be_two # 日期格式串每一个部分必须是两位数 # 否则按照算法iunrm_ 会变2 # 算了,按日期查找在iunrm_ 中实现后又删除了 # 敲日期太tm 麻烦了 - -b sub be_two ($) { my $num = shift; if ($num =~ /^\d$/) { $num = "0".$num; } return $num; } # sub print_help # 输出一个帮助说明 sub print_help { print <<_HELP; This is \033[1;37mirm_(rm for i)\033[0;37m by iSpeller Usage: irm_ [Options]... [file]... \033[1;32m-f\033[1;37m Do not ask before overwriting \033[1;32m-h|--help\033[1;37m Show this help \033[0;37mOption [file] alse can be [direction]. To remove a file whose name starts with a '-', for example '-foo', use one of these commands: irm_ -- -foo or: irm_ ./-foo PS: irm_ will ignore unexpect [Options] and [file] of "/", "/usr/bin/" _HELP exit 0; }
#!/usr/bin/perl # 程序连同irm_ 提供了一个简单的回收站机制 # 珍爱膝盖,防止中箭,爱生活,爱/dev/sda ;) # # PS 扔到/usr/bin/iunrm_ # By: iSpeller use warnings; use strict; use 5.010; our $recycle = "$ENV{HOME}/.recycle/"; our $data_file = "$recycle".".recycle_data"; # 我是猪函数~~~ MAIN: { # 只嫁Linux die "ERROR: Only run on GUN/Linux!\n\t" unless $^O =~ /^linux/i; # 没有$data_file 就不干活 say "\033[0;31m !!ERROR: \033[1;37mFile ", "[\e[1;31m$data_file\033[1;37m] ", "dose not exsit!\n", "\t\tRun [\e[1;31mirm_\033[1;37m] first!\033[0;37m" and exit 1 unless -e -d $recycle; # 空参打印帮助 print_help () if (0 == @ARGV); # 先检查数据文件 check_data (); # 一个冒牌的switch,用来解析参数 $_ = shift @ARGV; SWITCH: { /-h/i and do { # 参数是-h|--help print_help (); last SWITCH; }; # -s 会被当作-Sf 看待 /^-Sf?$/i and do { # 参数是-Sf. Search File search_file("-Sf", @ARGV); last SWITCH; }; /^-Sa?$/i and do { # 参数是-Sa, Search All file search_file ("-Sa"); last SWITCH; }; # -u 会被当作-Uf 看待 /^-Uf?$/i and do { # 参数是-Uf, Unrm File iunrm_ (@ARGV); last SWITCH; }; # -c 也会被当作-Cf 看待 /^-Cf?$/i and do { # 参数是-Cf, Clean File clean_file ("-Cf", @ARGV); last SWITCH; }; /^-Ca?$/i and do { # 参数是-Ca, Clean All clean_file ("-Ca"); last SWITCH; }; DEFAULT: say "\033[0;31m !!WARN: \033[1;37mUnkown Option ", "[\e[1;31m$_\033[1;37m]!\n\t\t", "run iunrm_ -h to show help.\033[0;37m"; exit 1; } # 更新数据文件 check_data (); exit 0; } # sub check_data # 检查$data_file, 记录中文件不存在则删除记录 sub check_data { my %data; # 读入数据 open (FILE, "<$data_file") or die "Can not open file: $data_file"; for () { my $old_name = $1 if /^"(.+)"_%MOVE_TO%_/; my $new_name = $1 if /_%MOVE_TO%_"(.+)"$/; $data{$old_name} = $new_name if (defined $old_name); } close FILE; # 检查数据 for (keys %data) { delete $data{$_} unless (-e $_); } # 重新写入数据文件 open (FILE, ">$data_file") or die "Can not open file: $data_file"; for (keys %data) { print FILE "\"$_\""."_%MOVE_TO%_"."\"$data{$_}\"\n"; } close FILE; } # clean_file # 删除回收站中和正则匹配的 sub clean_file { my $cmd = shift; my @args = @_; my @files; opendir (DIR, $recycle) or die "Can not open dir: $recycle!"; @files = readdir (DIR); closedir DIR; for (my $count=0; $count<@files; ++$count) { $files[$count] = $recycle.$files[$count]; } # 空的就直接更新数据文件后返回 say "\033[1;31mRecycle is empty!\033[0;37m" and check_data () and return unless (@files); # Ca 参数清空回收站 if ($cmd =~ /-Ca/i) { print "\033[1;31mWARN!! Really clean ALL ", "files in recycle?(y/n)\033[0;37m"; exit 1 if ( =~ /n/); for (@files) { next if m{($recycle)((.)|(..)|(.recycle_data))$}; qx/rm -r \"$_\"/; } say "\033[1;32mRecycle has been cleaned!\033[0;37m"; return; } # 按照参数正则匹配删除 for my $file (@files) { next if $file =~ m{($recycle)((.)|(..)|(.recycle_data))$}; for my $arg (@args) { my $regax = $arg; $regax .= '.*@\d+-\d+-\d+-\d+:\d+:\d+'; if ($file =~ /$regax/) { my $file_name = $1 if ($file =~ m{.*/(.+)@\d+-.+$}); say "\033[1;31m> \033[1;32mdelete \033[1;37m[$file_name]\033[0;37m"; qx/rm -r \"$file\"/; last; } } } } # sub search_file # 查询和正则匹配的文件 sub search_file { my $cmd = shift; my @files; my @data; if ($cmd =~ /^-sf/i) { # 根据文件名匹配 @files = @ARGV; } # 读入$data_file open (FILE, "<$data_file") or die "Can not open file: $data_file!"; for () { my $old_name = $1 if (/^"(.+)"_%MOVE_TO%_/); push @data, $old_name if (defined $old_name); } close FILE; # 分析参数并且按照匹配输出 SWITCH: { $cmd =~ /^-sa/i and do { # 参数-Sa,全部输出 for (@data) { my $file_name = $_; $file_name = $1 if ($file_name =~ m{.*/(.+)@\d+-.+$}); say "\033[1;31m>\033[1;32m found ", "\033[1;37m[$file_name]\033[0;37m"; } last SWITCH; }; $cmd =~ /^-sf/i and do { # 参数-Sf,按照文件匹配 my $file; for (@data) { $file = $1 if (m{/([^/]+@.+)$}); for (@files) { my $regax = $_; $regax =~ s/^\^(.*)\$$/$1/g; $regax .= '.*@\d+.+$'; if ($file =~ /$regax/) { my $file_name = $1 if ($file =~ /(.+)@\d+-.+$/); say "\033[1;31m>\033[1;32m found ", "\033[1;37m[$file_name]\033[0;37m"; } } } last SWITCH; }; DEFAULT: die "U got a big trouble, boy."; } } # sub iunrm_ # 恢复符合正则参数的文件 # unrm for i sub iunrm_ { my @files = @_; my %data; # 从数据文件建立哈希 open (FILE, "<$data_file") or die "Can not open file: $data_file"; for () { my $old_name = $1 if (/^(".+")_%MOVE_TO%_/); my $new_name = $1 if (/_%MOVE_TO%_(".+")$/); $data{$old_name} = $new_name; } close FILE; # 删除匹配的文件名参数 for my $file (@files) { my $regax = $file; $regax =~ s/^\^?(.*)\$?$/$1/g; for my $file_name (keys %data) { # 如果正则匹配 if ($data{$file_name} =~ /$regax/) { # 构造指令并且执行 my $cmd = sprintf "mv -i %s %s", $file_name, $data{$file_name}; qx/$cmd/ and delete $data{$file_name}; # 打印下删除信息 my $file_to = $data{$file_name}; $file_name = $1 if ($file_name =~ m{.*/(.+)}); $file_name =~ s/^(.+)@\d+-.+"$/$1/g; say "\033[1;31m> \033[1;32m process ", "\033[1;37m [$file_name]\033[1;32m to ", "\033[1;37m [$file_to]\033[0;37m"; } } } } # sub print_help # 打印iunrm_ 的帮助 sub print_help { print <<_HELP; This is \033[1;37miumrm_(umrm for i)\033[0;37m by iSpeller Usage: iumrm_ [Options]... [file]... \033[1;32m-Sf|-s\033[1;37m Search by File-name (Regax) \033[1;32m-Sa\033[1;37m Search All \033[1;32m-Cf|-c\033[1;37m Clean File (Regax) of recycle \033[1;32m-Ca\033[1;37m Clean All file of recycle \033[1;32m-Uf|-u\033[1;37m Unrm File-name (Regax) \033[1;32m-h|--help\033[1;37m Show this help \033[0;37mOption [file] alse can be [direction]. PS: You Can Use Perl Regax As [file]... Example: iunrm_ -u "^red-.+" "low\\h.+l" ^^ It will unrm file like "red-dog" or "yellow apple" in recycle. _HELP exit 0; }
相关推荐
Linux 是一个真正的多用户操作系统,可以同时接受多个用户登录,还允许一个用户进行多次登录。这是因为Linux和许多版本的Unix一样,提供了虚拟控制台的访问方式,允许用户在同一时间从控制台(系统的控制台是与系统...
【新增】版主管理面板 - 主题回收站,版主可对回收站的主题进行搜索、查看,管理员可进行恢复和彻底删除 【新增】版主管理面板 - 审核用户,管理员可在后台设置某个版主协助进行会员审核 【增强】版主管理面板 - ...
修改主目录:转到“主目录”窗口,再在“本地路径”输入(或用“浏览”按钮选择)好自己网页所在的“D:\Wy”目录。 3.添加首页文件名:转到“文档”窗口,再按“添加”按钮,根据提示在“默认文档名”后输入自己...
下列命令示例向指定设备写入一个新的主引导记录: fixmbr DeviceHardDisk0 注意 如果不指定 device_name,新的主引导记录将被写入引导设备,即装载主系统的驱动器。 如果系统检测到无效或非标准分区表标记...
实例089 关闭IE主窗口时,不弹出询问对话框 132 实例090 弹出提示对话框并重定向网页 133 3.8 弹出网页对话框 134 实例091 弹出全屏显示的网页模式对话框 134 实例092 网页拾色器 136 实例093 日期选择器...
对于那些已经不用的用户应给予清除,权限过界的用户应及时回收权限,回收权限可以通过更新User表相应字段,也可以使用REVOKE操作。 下面给出本人从其它资料(www.cn-java.com)获得的对常用权限的解释: 全局管理权限...
对于那些已经不用的用户应给予清除,权限过界的用户应及时回收权限,回收权限可以通过更新User表相应字段,也可以使用REVOKE操作。 下面给出本人从其它资料(www.cn-java.com)获得的对常用权限的解释: 全局管理...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 freeeim_FreeEIM_企业即时通讯软件源代码2010年8月份最新版 FTP、HTTP 多线程断点续传下载文件 源码 gdiplus应用实例 ...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 freeeim_FreeEIM_企业即时通讯软件源代码2010年8月份最新版 FTP、HTTP 多线程断点续传下载文件 源码 gdiplus应用实例 ...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 freeeim_FreeEIM_企业即时通讯软件源代码2010年8月份最新版 FTP、HTTP 多线程断点续传下载文件 源码 gdiplus应用实例 ...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 freeeim_FreeEIM_企业即时通讯软件源代码2010年8月份最新版 FTP、HTTP 多线程断点续传下载文件 源码 gdiplus应用实例 ...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 freeeim_FreeEIM_企业即时通讯软件源代码2010年8月份最新版 FTP、HTTP 多线程断点续传下载文件 源码 gdiplus应用实例 ...
例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望...
本书分为5篇15章,共计625个实例和625个经验技巧。每个实例都经作者精心筛选,具有很强的实用性,其中一些实例是开发人员难于寻觅的解决方案。 本书适合PHP的初学者,如高校学生、求职人员作为练习、速查、学习...
本书分为5篇15章,共计625个实例和625个经验技巧。每个实例都经作者精心筛选,具有很强的实用性,其中一些实例是开发人员难于寻觅的解决方案。 本书适合PHP的初学者,如高校学生、求职人员作为练习、速查、学习...
例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望...
另外有只打开一个应用程序、CRichEdit的使用、最小到托盘、自动检测在线用户(多播组)等。 FreeBird2011Dlg.h 主对话框类头文件 MultiGroup.h 多播组类头文件 UserLink.h 用户链表类头文件 ListenSocket.h 侦听接口...