del 替代 rm 的自用脚本

sh/bash/dash/ksh/zsh等Shell脚本
回复
aBiNg
帖子: 1331
注册时间: 2006-07-09 12:22
来自: 南京

del 替代 rm 的自用脚本

#1

帖子 aBiNg »

1、引言
必要性自不必说,实现的方式有多种。本帖只是想按照自己的思路写成脚本,放到$PATH里面。也许也可作纯技术讨论,如果能算作“技术”。:wink:

2、示例
简单的debug了几天,对于文件名不算太复杂的都应该可以处理。例如:

代码: 全选

aBiNg:~ ¶ mkdir -p zzz/zz/z
aBiNg:~ ¶ touch zzz/{a,a.mp3,b.mp3} zzz/zz/a
aBiNg:~ ¶ del zzz/*.mp3 ~/zzz/a /home/wujie/zzz/zz/a zzz/zz/z/
aBiNg:~ ¶ t
aBiNg:~/.Trash ¶ ll
total 4
-rw-r--r-- 1 wujie wujie    0 2008-02-25 17:29 home::wujie::zzz::a>>2008-02-25@17:30:55
-rw-r--r-- 1 wujie wujie    0 2008-02-25 17:29 home::wujie::zzz::zz::a>>2008-02-25@17:30:55
-rw-r--r-- 1 wujie wujie    0 2008-02-25 17:29 zzz::a.mp3>>2008-02-25@17:30:55
-rw-r--r-- 1 wujie wujie    0 2008-02-25 17:29 zzz::b.mp3>>2008-02-25@17:30:55
drwxr-xr-x 2 wujie wujie 4096 2008-02-25 17:28 zzz::zz::z>>2008-02-25@17:30:55
aBiNg:~/.Trash ¶ more .file_deleted_path 
2008-02-25@17:30:55 -f /home/wujie/zzz/a.mp3
2008-02-25@17:30:55 -f /home/wujie/zzz/b.mp3
2008-02-25@17:30:55 -f /home/wujie/zzz/a
2008-02-25@17:30:55 -f /home/wujie/zzz/zz/a
2008-02-25@17:30:55 -d /home/wujie/zzz/zz/z
aBiNg:~/.Trash ¶ undel *
' /home/wujie/zzz/a ' has been recovered.
' /home/wujie/zzz/zz/a ' has been recovered.
' /home/wujie/zzz/a.mp3 ' has been recovered.
' /home/wujie/zzz/b.mp3 ' has been recovered.
' /home/wujie/zzz/zz/z ' has been recovered.
aBiNg:~/.Trash ¶ more .file_deleted_path
aBiNg:~/.Trash ¶ cd
aBiNg:~ ¶ ls -R zzz/
zzz/:
a  a.mp3  b.mp3  zz

zzz/zz:
a  z

zzz/zz/z:
3、思路
从上面的输出大概也能看到点思路。

就是先将file的有关属性存放起来,修改,再加到"~/.Trash/.file_deleted_path"文件里面,形成一个档案备份,以利于'undel'命令的恢复文件;恢复之后,同时清空掉档案备份中的对应项即可。

因为实际执行的是mv,所以执行速度上无需多虑。想真正删除文件,rm即可。

获得与释放文件属性是本脚本的麻烦之处,用了许多字符处理的操作,所以我担心:当文件名很复杂(含有太多不常用字符)时,可能就不能胜任了,还请诸位不吝赐教。

4、内容
脚本内容:

代码: 全选

aBiNg:~/script ¶ more del undel 

代码: 全选

::::::::::::::
del
::::::::::::::
#!/bin/bash
# the customized command 'del' used to replace 'rm' command
# written by [email protected]
# completed at 2008-02-24

current_dir=`pwd`
deltime=`date +%F@%T`
storage=~/.Trash/.file_deleted_path
delimiter='>>'

[ $current_dir == `dirname $storage` ] && \
echo "you should not run 'del' command in ~/.Trash directory!" && \
exit

[ ! -f $storage ] && touch $storage

for fname in "$@"
do
	# erase backslashed '\' and last character if it's a slash '/'
	tmp=`echo $fname | sed 's/\(.*\)\/$/\1/'`
	base=`basename $tmp`

	# finalepath/name check
	if [ "${fname:0:1}" == '/' -o "${fname:0:1}" == '~' ]
	then
		finalpath=$tmp
		finalname=`echo $tmp | sed 's!/!::!g' | sed 's!::!/!'`$delimiter$deltime
	else
		finalpath=$current_dir/$tmp
		finalname=`echo $tmp | sed 's!/!::!g'`$delimiter$deltime
	fi

	[ -f $tmp ] && filetype='-f'
	[ -d $tmp ] && filetype='-d'

	[ x"" == x"$filetype" ] && \
	echo "Error, ' $base 'does not exist!" && \
	continue

	# add deleted archive's profiles to $storage
	echo "$deltime $filetype $finalpath" >> $storage

	mv $finalpath ~/.Trash/$finalname
done

代码: 全选

::::::::::::::
undel
::::::::::::::
#!/bin/bash
# 'undel' used to recovery deleted files done by 'del'
# written by [email protected]
# completed at 2008-02-24

storage=~/.Trash/.file_deleted_path

[ `pwd` != `dirname $storage` ] && \
echo "you should run 'undel' command in ~/.Trash directory!" && \
exit

for delfname in "$@"
do
	# erase backslashes '\' and last character if it's a slash '/'
	tmpname=$(basename $(echo "$delfname"))
	mn=$(($(echo "$tmpname" | grep "::" -o | wc -l)+1))

	# get the file's realname and deleted time
	corename=${tmpname%%>>*}
	deltime=${tmpname##*>>}
	realname=`echo "$corename" | sed 's!::!/!g'`

	[ -f $tmpname ] && filetype="-f"
	[ -d $tmpname ] && filetype="-d"

	patharray=$(grep $deltime $storage | awk '$2=="'$filetype'" {print $3}')

	# get sections of the undeleted file's corepath


	for path in $patharray
	do
		for i in `seq $mn`
		do
			array[$i]=`echo "$path" | rev | cut -d '/' -f "$i" | rev`
			cpath[1]=${array[1]}
			[ $i -gt 1 ] && cpath[$i]=${array[$i]}/${cpath[$((i-1))]}
		done

		[ "${cpath[$mn]}" == "$realname" ] && fpath=$path && \
		break
	done

	[ x"$fpath" == x"" ] && \
	echo "cann't find the path of ' $tmpname ', nothing done!" && \
	continue

	# update $storage file
	ml=$(cat -n $storage | sed -ne "/$deltime/{/$filetype/p}" | \
	awk '$4=="'$fpath'" {print $1}')

	sed "$ml d" $storage > /tmp/storage.new
	mv /tmp/storage.new $storage

	# finish the job <-- replace 'rm' by 'mv'
	dirpath=`dirname $fpath`
	[ ! -d $dirpath ] && mkdir -p $dirpath
	if [ ! -f $fpath ]
	then
		mv $delfname $fpath && \
		echo "' $fpath ' has been recovered."
	else
		echo "' $fpath ' exists, nothing done!"
	fi
done
tongttt
帖子: 444
注册时间: 2007-11-27 22:20

#2

帖子 tongttt »

学习shell中
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#3

帖子 xiooli »

lz的意思是类似回收站的还原功能吗?貌似最新的gnome支持回收站还原了呢
aBiNg
帖子: 1331
注册时间: 2006-07-09 12:22
来自: 南京

#4

帖子 aBiNg »

xiooli
嗯,是还原的意思。但是命令行操作的,不是nautilus(你指gnome中默认的这个吧?)。

rm 命令与gnome无关啊,而我自己不用gnome,呵呵。

对于常在shell中管理系统的,可能有点用途吧。
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

#5

帖子 xiooli »

aBiNg 写了:xiooli
嗯,是还原的意思。但是命令行操作的,不是nautilus(你指gnome中默认的这个吧?)。

rm 命令与gnome无关啊,而我自己不用gnome,呵呵。

对于常在shell中管理系统的,可能有点用途吧。
如果是命令行的话,确实挺有用
回复