修改rm命令以避免誤刪
阿新 • • 發佈:2019-01-09
問題重現
是否碰到過如下情況:
- 寫了一個月的程式碼,沒有做本地提交,手滑來了個
rm -rf
,然後就沒有然後了。 - 並沒有注意一個名叫~的資料夾,有一丟丟潔癖的自己習慣性的
rm -rf ~
,一回車,世界突然安靜。 - … …
大概的解決方案都是1. 找個地方,2. rm改為mv, 實現rm時把檔案直接mv到這個地方,3. 提供清空回收站/查看回收站檔案/找回誤刪檔案等的操作。
基本需求
基本功能參考windows中的回收站。
- 準備一個資料夾,作為垃圾回收站(~/.trash);
- 刪除檔案:輕鬆將需要刪除的檔案移動到回收站中,支援資料夾及檔案;支援絕對路徑和相對路徑;支援重名檔案;
- 清空回收站:徹底刪除回收站中的檔案及相關資源;
- 查看回收站檔案列表:羅列回收站中的檔案,羅列回收站中的檔案的恢復路徑;
- 恢復某個檔案:按照恢復路徑及原始檔名稱恢復檔案,該命令應具有自動補全功能;
- 重構rm命令,替換其功能;
- 提供簡潔的命令訪問;
開發過程
準備全域性變數
export HOME_TRASH_PATH=~/.trash # 回收站的位置
export TRASH_FILE_LIST=$HOME_TRASH_PATH/.list # 用於存放原始檔案的路徑
# 建立回收站
if [ ! -d "$HOME_TRASH_PATH" ]; then
mkdir -p "$HOME_TRASH_PATH "
fi
# 建立回收記錄
if [ ! -f "$TRASH_FILE_LIST" ]; then
touch "$TRASH_FILE_LIST"
fi
HOME_TRASH_PATH
提供了回收站的位置,該功能只在當前使用者環境下生效,故採用~目錄;避免不同使用者使用可能存在的許可權問題。
TRASH_FILE_LIST
檔案為文字檔案,用於存放原始檔案的路徑,為恢復檔案提供依據;
刪除檔案
function _trash_delete()
{
local trash_path=$HOME_TRASH_PATH
local trash_nanme
local file_name
local file_path
# 應支援多個檔案(夾)一起刪除
for tmp_path in [email protected];
do
# 從引數中分離出檔案路徑和檔名
# 利用IFS分割Unix風格的檔案路徑
local old_ifs="$IFS"
IFS="/"
local file_array=($tmp_path)
IFS="$old_ifs"
# 陣列中最後一個為檔名, 注意冒號後有個空格
local length=${#file_array[@]}
file_name=${file_array[@]: -1}
# 指定檔名為"名.時間",避免重名,同時日期可以提供找回的參考
trash_name=$file_name.`date +%Y%m%d-%H:%M:%S`
# 獲取第一個字元確認是否為絕對路徑
local _prefix=${tmp_path:0:1}
if [ "/" = $_prefix -o "~" = $_prefix ]; then
# 絕對路徑只需要去掉檔名就可以獲得路徑,eg:/home/aaa/test_dir
file_path=${tmp_path%/$file_name*}
else
# 相對路徑需要解析出部分路徑後與當前路徑疊加
file_path=${tmp_path%/$file_name*}
file_path=`pwd`"/$file_path"
fi
# 將路徑寫入TRASH_FILE_LIST檔案
echo -e "$trash_name \t\t $file_path" >> $TRASH_FILE_LIST
# 將檔案mv到回收站中
mv $tmp_path $HOME_TRASH_PATH/$trash_name
done
}
顯示回收站中的檔案
# 顯示回收站中垃圾清單
function _trash_list()
{
# 為輸出加上頭
echo -e "==== Garbage Lists in $HOME_TRASH_PATH ===="
_trash_help
# 列表檔案
ls -a $HOME_TRASH_PATH
}
顯示回收站中的檔案及路徑
function _trash_path()
{
# TRASH_FILE_LIST中的檔案結構如下
# c.c.20180531-20:05:57 /home/aaa/test
# a.b.20180531-20:06:54 /home/aaa/test/file_path
# b.c.20180531-20:07:32 /home/aaa/test/file_path
# b.a.20180531-20:10:51 /home/aaa/test/./b.b
# 頭
echo -e "------------bakup name---------------recover path"
# 輸出檔案及路徑
cat $TRASH_FILE_LIST
}
恢復檔案
# 找回回收站相應檔案
function _trash_recover()
{
local rfile_name= # 需要恢復的檔名
local file_name= # 原始檔名
local file_path= # 原始檔案路徑
# 同時支援多個檔案的恢復
for tmp_path in [email protected];
do
# 首先判斷檔案(夾)的存在性,以防mv時出錯
if [[ ! -d "$HOME_TRASH_PATH/$tmp_path" ]] && [[ ! -f "$HOME_TRASH_PATH/$tmp_path" ]]; then
echo "no such file : $tmp_path"
continue
fi
rfile_name=$tmp_path
# 匹配去除(.時間)還原真實檔名
file_name=${rfile_name%\.*}
# 通過cat/grep/awk獲取TRASH_FILE_LIST中檔案的原始路徑
file_path=`cat $TRASH_FILE_LIST | grep "$rfile_name" | awk '{print $2}'`
# 刪除該記錄,todo
# 將檔案搬移回原始目錄中
mv $HOME_TRASH_PATH/$rfile_name $file_path/$file_name
done
}
清空回收站
function _trash_clean()
{
# 以醒目的字型要求再次確認,以免誤刪
echo -ne "\033[33mClear all trashes in $HOME_TRASH_PATH, Sure?[y/n]\033[0m"
read confirm
if [ $confirm == "y" -o $confirm == "Y" ] ;then
# 呼叫系統rm刪除HOME_TRASH_PATH下的所有檔案
/bin/rm -rf $HOME_TRASH_PATH/*
/bin/rm -rf $HOME_TRASH_PATH/.* 2>/dev/null
fi
}
命令重構
trash()
{
# 指定對不同引數的解析
local arg=$1
shift
case "$arg" in
-d)
_trash_delete [email protected]
;;
-l)
_trash_list
;;
-r)
_trash_recover [email protected]
;;
-c)
_trash_clean
;;
-p)
_trash_path
;;
-h|*)
_trash_help
;;
esac
}
alias rm="trash -d" # 重構rm
# 以下內容修改使用,視具體環境
alias rl="trash -l" # 這些命令基本在系統中並未用到,所以才如此使用
alias rr="trash -r"
alias rp="trash -p"
alias rc="trash -c"
alias rh="trash -h"
使用說明
function _trash_help()
{
echo -e "\033[33m----Usage------\033[0m"
echo -e "\033[33m-1- Use "trash -p" or "rp" to list all garbages and real pathes in $HOME_TRASH_PATH\033[0m"
echo -e "\033[33m-1- Use "trash -l" or "rl" to list all garbages in $HOME_TRASH_PATH\033[0m"
echo -e "\033[33m-1- Use "trash -c" or "rc" to clear all garbages in $HOME_TRASH_PATH\033[0m"
echo -e "\033[33m-2- Use "trash -d" or "rm" to mv the file into $HOME_TRASH_PATH\033[0m"
echo -e "\033[33m-2- Use "trash -r" to "rr" to mv the file in garbages to current dir\033[0m"
echo -e "\033[33m-2- Use "trash -h" to "rh" to show help \033[0m"
}
自動補全
function _cmp_rr()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
local options=`ls $HOME_TRASH_PATH`
COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )
}
# 自行查閱complete的用法 complete -F FUNC COMMAND
# -F指定了後面的函式執行結果作為COMMAND的補全內容
complete -F _cmp_rr rr
自啟動
# 將檔案放入~目錄下,命名為(.bash_trash),並在~/.bashrc中新增如下程式碼即可
if [ -f ~/.bash_trash ]; then
. ~/.bash_trash
fi
基本測試
# 命令舉例
# 命令連續執行
# pwd = ~/test
# 建立所需檔案
$ mkdir a b c
$ touch a/a.a a/a.b a/a.c b/b.a b/b.b b/b.c
$ tree
.
├── a
│ ├── a.a
│ ├── a.b
│ └── a.c
├── b
│ ├── b.a
│ ├── b.b
│ └── b.c
└── c
3 directories, 6 files
# 測試絕對路徑
$ rm /home/aaa/test/a/a.a
$ ls a
a.b a.c
# 測試絕對路徑
$ rm ~/test/a/a.b
$ ls a
a.c
# 測試相對路徑
$ rm ./a/a.c
$ ls a
# 測試多個檔案
$ rm b/b.a b/b.b b/b.c
$ ls b
# 測試萬用字元
$ rm *
$ ls
# 測試檔案列表
$ rl
==== Garbage Lists in /home/aaa/.trash ====
----Usage------
-1- Use trash -p or rp to list all garbages and real pathes in /home/aaa/.trash
-1- Use trash -l or rl to list all garbages in /home/aaa/.trash
-1- Use trash -c or rc to clear all garbages in /home/aaa/.trash
-2- Use trash -d or rm to mv the file into /home/aaa/.trash
-2- Use trash -r to rr to mv the file in garbages to current dir
-2- Use trash -h to rh to show help
. a.b.20180531-20:52:24 b.b.20180531-20:53:01
.. a.c.20180531-20:52:39 b.c.20180531-20:53:01
a.20180531-20:53:16 b.20180531-20:53:16 c.20180531-20:53:16
a.a.20180531-20:52:06 b.a.20180531-20:53:01 .list
# 測試檔案路徑
$ rp
------------bakup name---------------recover path
a.a.20180531-20:52:06 /home/aaa/test/a
a.b.20180531-20:52:24 /home/aaa/test/a
a.c.20180531-20:52:39 /home/aaa/test/./a
b.a.20180531-20:53:01 /home/aaa/test/b
b.b.20180531-20:53:01 /home/aaa/test/b
b.c.20180531-20:53:01 /home/aaa/test/b
a.20180531-20:53:16 /home/aaa/test/a
b.20180531-20:53:16 /home/aaa/test/b
c.20180531-20:53:16 /home/aaa/test/c
# 測試補全,rr後敲擊2次tab
$ rr [tab][tab]
a.20180531-20:53:16 a.c.20180531-20:52:39 b.b.20180531-20:53:01
a.a.20180531-20:52:06 b.20180531-20:53:16 b.c.20180531-20:53:01
a.b.20180531-20:52:24 b.a.20180531-20:53:01 c.20180531-20:53:16
# 測試恢復檔案
$ rr a.a.20180531-20:52:06
$ tree
.
└── a
└── a.a
1 directory, 1 file
大功告成。
相關連結
更多更及時的部落格更新請戳—> KingRumn