Linux回收站的設計與實現

作爲Linux系統管理員或者軟件開發人員,當你使用rm命令刪除文件之後發現該文件依然有用但無法恢復,或者使用 ‘rm -rf’強制誤刪了某些文件時,是否爲此感到痛苦不堪。是否苦惱於Linux缺乏類似Windows系統的回收站。雖然某些Linux圖形界面具有回收站功能,但是在命令行中依然缺乏回收站功能的支持。本文通過shell腳本實現一個回收站命令trash,提供基於Linux系統命令行的回收站功能,讓誤刪的文件能夠恢復如初。在多數情況下,你可以使用trash命令替代rm命令進行刪除文件操作。此命令可運行在帶bash的Linux server、Linux桌面系統、嵌入式Linux系統上。

回收站功能簡介

通過usage函數顯示trash命令的幫助信息。

function usage(){
            echo "Function: Put files or directories in trashcan."
            echo "Usage: trash [OPTION]... FILE..."
            echo "Options:"
            echo "    -h | -help        Show the help mesage"
            echo "    -t | -trash       Move contents to trashcan"
            echo "    -f | -force       Delete contents forcely"
            echo "    -l | -list        List contents in trashcan"
            echo "    -r | -restore     Restore the contents in trashcan"
            echo "    -d | -delete      Delete contents from trashcan"
            echo "    -e | -empty       Empty trashcan"    
            echo "    -c | -config      Configure crontab task,empty trashcan regularly"
    }

執行trash -h或者trash不帶參數時,顯示trash命令幫助信息如下:

這裏寫圖片描述

trash命令刪除文件時,實際上是將文件移動到用戶根目錄的trashcan目錄中,同時將文件名、刪除時間、原始路徑記錄在.record隱藏文件中;通過trash -r選項可將文件從回收站中恢復到原始路徑;確信文件可刪除的情況下,可使用trash -f進行徹底刪除操作;trash -d和-e選項用於清除回收站中文件;執行trash -c將清理回收站指令添加到crontab任務中,系統會定期自動清理回收站。

初始化

運行trash命令時,首先進行初始化,代碼片段如下:

PATH_TRASHCAN=~/trashcan
PATH_RECORD=$PATH_TRASHCAN/.record
PATH_CRON=/var/spool/cron
function init(){
    if [ ! -d $PATH_TRASHCAN ]
        then
        mkdir $PATH_TRASHCAN
        chmod 600 $PATH_TRASHCAN
    fi
}

定義回收站目錄,用於存放刪除的文件或者文件夾。Trash命令在當前用戶根目錄中新建trashcan目錄來存放文件。如代碼所示,init函數首先判斷trashcan目錄是否存在,如果不存在,則新建該目錄且將trashcan目錄權限設置爲當前用戶可讀寫,禁止其他用戶對trashcan目錄的訪問權限。

參數判斷以及處理

初始化完成之後,需要對trash命令的參數進行判斷和處理。

    if [ $# -ge 1 ]
    then    
        declare param=()
            param_circle=0
        for i in $@; do
        param[param_circle]=$i
        param_circle=$(($param_circle+1))
        done
        unset param[0]      
        case "$1" in
        -h)
                usage
                ;;
        -t)         
               trash    
                ;;
        -f)
                force
                ;;
        -l)
                list
                ;;
        -r)
                restore
                ;;
        -d)
                delete
                ;;
        -e)
               empty
                ;;            
        -c)
                config 
                ;;
        -o)
                cron_delete 
                ;;
         *)
                echo "$1 is not an option"
                usage
                ;;
          esac

else
    usage  
fi

首先判斷trash命令輸入的參數個數,如果小於1,則調用usage函數提示用戶trash命令的正確使用方法。如果大於等於1,證明trash命令使用方式合法,此時將所有參數存放到param數組中,使用unset param[0]刪除第一個參數,保留所有文件名內容在param數組。接下來根據第一個參數的值,分別調用相應的函數。

刪除文件到回收站

功能說明

  • 當輸入trash -t 時調用trash函數將文件移動到回收站。判斷param數組長度,如果小於1說明trash -t後沒有指定被刪除文件名稱;如果大於等於1則循環處理輸入的所有文件。
  • 當文件、文件夾大於200M時對其進行強制刪除,考慮到大多數嵌入式平臺Flash存儲空間非常有限。
  • 給被刪除文件添加時間戳,目的是通過時間戳區別同名文件且能夠清晰顯示刪除時間。
  • 獲取被刪除文件的原始路徑,以便從回收站恢復。
  • 調用record函數記錄刪除文件信息。
  • 通過mv命令將文件移動到trashcan目錄中。
function trash(){
    if [ ${#param[@]} -lt 1 ]
        then
        echo "Please input the files you want to trash!"
        echo ">trash -t [file1]..."
    else
        file_circle=1
        TotalFileSize=0
        for file in ${param[@]}
         do
            if [ -f "$file" ] 
                then
                    fileSize=`ls -l $file|awk ' {print $5}'` 
                    if [ $fileSize -gt $(( 200*1024*1024 )) ]
                        then
                        echo "$file size is larger than 200M, will be deleted directly"
                        `rm -rf $file`
                        unset param[$file_circle]

                    else
                        TotalFileSize=$[TotalFileSize+fileSize]
                    fi
            elif [ -d "$file" ] 
                then
                    dirSize=`du -sb $file|awk '{print $1}'`
                    if [ $dirSize -gt $(( 200*1024*1024 )) ]
                        then
                        echo "dir: $file size is larger than 200M, will be deleted directly"
                        `rm -rf $file`
                        unset param[$file_circle]
                    else
                        TotalFileSize=$[TotalFileSize+dirSize]
                    fi
            fi
        file_circle=`expr $file_circle + 1`        
        done        

        for file in ${param[@]}
        do
            currentTime=`date +%Y-%m-%d_%H:%M:%S`
            trashFile="${file##*/}_${currentTime}"
            trashPath="$(pwd)/$file"        
            if mv -f $file $PATH_TRASHCAN/$trashFile
             then 
                record $trashFile $trashPath
                echo "$file is trashed"
            fi
        done        

    fi
}

record函數

將帶有時間戳的文件名以及文件的原始路徑記錄在~/trashcan/.record文件中。

PATH_RECORD=$PATH_TRASHCAN/.record
function record(){
    if [ ! -f $PATH_RECORD ]
    then 
        touch $PATH_RECORD
        chmod 644 $PATH_RECORD
    fi
        echo $1 $2>> $PATH_RECORD
}

強制刪除

如果想要徹底刪除文件可以使用trash -f,調用force函數通過rm -rf命令強制刪除文件或者目錄。

function force(){
    rm -rf ${param[@]}
}

使用示例如下:

這裏寫圖片描述

通過ll -a ~/trashcan顯示trashcan目錄爲空。trash_test爲刪除文件的原始目錄,其中具有file1和file2兩個文件。執行trash -t file1 file2將file1和file2刪除到回收站trashcan中,執行後可以發現回收站中產生了file1和file2帶時間戳的文件,同時trash_test目錄中相應的文件消失。

顯示回收站內容

function list(){
    cat $PATH_RECORD
}

通過trash -l命令可隨時隨地查看回收站內容,不用訪問回收站目錄去查看。可以看到所有刪除的文件名、刪除時間、原始路徑。

恢復文件

  • 輸入trash -r [FILE]將FILE文件恢復到原始路徑。
  • 首先判斷trash -r後面是否輸入了文件名,若沒有則提示用戶輸入。
  • 從.record文件中找到恢復文件的原始路徑。
  • 通過mv將文件移動到原始路徑。
  • 同時將恢復的文件記錄從.record文件中刪除。
function restore(){

    if [ ${#param[@]} -lt 1 ]
        then
        echo "Please input the files you want to restore!"
        echo ">trash -r [file1]..."
    else

        for file in ${param[@]}
         do
            restorePath=$(awk /$file/'{print $2}' $PATH_RECORD) 
            fileRestore=$(awk /$file/'{print $1}' $PATH_RECORD)
            $(mv  $PATH_TRASHCAN/$fileRestore $restorePath)
            echo "$fileRestore is restored to $restorePath"
            $(sed -i /$fileRestore/'d' $PATH_RECORD)
        done
    fi
}

使用示例如下:

這裏寫圖片描述

通過以上示例可以發現回收站中具有file1和file2兩個帶有時間戳的文件,且.record中記錄了原始路徑,此時trash_test目錄爲空。執行trash -r file*命令恢復所有file開頭的文件,成功恢復了file1和file2文件,且刪除了.record中的記錄信息。

清理回收站

手動刪除

  • 通過trash -d刪除指定文件。
  • Delete函數首先判斷trash -d是否指定了文件。如果爲空則提示用戶輸入想要刪除的回收站中文件。
    反之,循環處理文件。使用rm -rf徹底刪除文件或者文件夾。
  • 同時將文件記錄從.record文件中刪除。
function delete(){
    if [ ${#param[@]} -lt 1 ]
        then
        echo "Please input the files you want to restore!"
        echo ">trash -d [file1]..."
    else
        for file in ${param[@]}
         do
            fileDelete=$(awk /$file/'{print $1}' $PATH_RECORD)
            $(rm -rf $fileDelete)
            echo "$fileDelete is deleted"
            $(sed -i /$fileDelete/'d' $PATH_RECORD)
        done
    fi
}

清空回收站

  • 通過trash -e命令清除回收站中所有內容。
  • Empty函數調用rm -rf刪除~/trashcan目錄中的所有文件以及隱藏文件.record。
function empty(){
    rm -rf $PATH_TRASHCAN/*
    rm -rf $PATH_RECORD
}

crontab自動清理

  • 配置crontab任務,每隔30分鐘刪除回收站中存放時間大於7天的文件。
  • 執行trash -c將定期清除回收站文件的指令加入到crontab中。
  • 通過crontab -l新建用戶cron文件。
  • 設置爲每隔30分鐘執行一次清理操作,該時間可靈活調整。
echo "*/30 * * * * trash -o $regularTime " >> $PATH_CRON/$USER
  • trash -c後參數爲天數,如果爲空則默認每隔30分鐘刪除回收站中存放超過7天的文件,否則刪除超過指定天數的文件。
    配置crontab任務函數config代碼清單:
function config(){
    if [ ${#param[@]} -lt 1 ]
    then 
        regularTime=7
    else
        regularTime=${param[1]}
    fi
    crontab -l > $PATH_CRON/$USER
    # echo "* * * * * echo "delete files which were older than $regularTime days">`tty` " >> $PATH_CRON/$USER
    $(sed -i /trash/'d' $PATH_CRON/$USER)
    echo "*/30 * * * * trash -o $regularTime " >> $PATH_CRON/$USER
    crontab $PATH_CRON/$USER
    crontab -l

}

定期清除函數:

function cron_delete(){
    if [ ${#param[@]} -lt 1 ]
    then 
        regularTime=7
    else
        regularTime=${param[1]}
    fi
    arrayCron=($(find $PATH_TRASHCAN/* -mtime +$regularTime))
    for file in ${arrayCron[@]}
    do
        $(rm -rf $file)
    fileRecord="${file##*/}"
        $(sed -i /$fileRecord/'d' $PATH_RECORD)
    done
}

使用示例如下:

這裏寫圖片描述

終端顯示*/30 * * * * trash -o 8則表示該任務已成功添加到crontab中。
注意:
PATH_CRON=/var/spool/cron
該路徑需根據用戶系統實際路徑更改。例如:ubuntu實際路徑爲/var/spool/cron/contabs。

總結

本文使用shell腳本實現了簡易的命令行Linux回收站功能。用戶只需將trash腳本拷貝到Linux環境變量目錄中,給予執行權限,即可使用該功能,建議使用trash命令替代rm命令進行刪除操作,減少誤刪造成的損失。

源碼地址:https://github.com/IOT-er/trashcan

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章