首页 > 系统相关 >Shell 实现终端 rm 回收站效果

Shell 实现终端 rm 回收站效果

时间:2023-08-15 20:56:36浏览次数:42  
标签:Shell option echo file fi reply rm trash 回收站

本次实现的 rm 脚本的功能有:

  1. 回收站收容删除的文件
  2. 脚本记录删除的文件绝对路径和时间戳
  3. 可根据脚本恢复删除的文件,并且可以只根据文件名匹配回收站所有的文件进行选择
  4. 可直接删除文件
  5. 可同时接收多个参数
  6. 清空回收站

后续会更新定时清空回收站的功能。

TRASH_DIR="$HOME/.trash"
LOG_FILE="${TRASH_DIR}/.log"
VERSION="1.0"
NAME="rm"


# trash dir path: $TRASH_DIR
# create dir if not exists
if [ ! -d "$TRASH_DIR" ]
then mkdir -v "$TRASH_DIR"
fi

if [ ! -f "$LOG_FILE" ]
then touch "$LOG_FILE"
fi

error() {
    #echo -e "\e[1;31m[ERROR] ${1}\e[0m"
    :
}

debug() {
    #echo -e "\e[1;32m[DEBUG] ${1}\e[0m"
    :
}

usage()
{
    echo -e "Usage: delete [options] [file1 file2 file3....]\n"
    echo "delete is a simple command line interface for deleting file to custom trash."
    echo "Options:"
    echo "  -c | --clear    Empty the trash"
    echo "  -f | --force    Force delete file instead of moving into trash"
    echo "  -r | --restore  Restore the file in the trash"
    echo "  -l | --list     List the files in the trash"
    echo "  -p | --print    Print log file"
    echo "  -h | --help     Show this help message and exit"
    echo "  -v | --version  Show program's version number and exit"
    echo "  -t | --trash    Set default trash can path, this option has peermanent effect"
}

version() {
    echo "${NAME} (Trash Collection) 1.0"
}

print_log() {
    cat "${LOG_FILE}"
}

list() {
    ls "${TRASH_DIR}"
}

set_trash() {
    if [[ $# -eq 0 ]]; then
        echo "${NAME}: '-t' option missing trash can path"
        exit 1
    fi
    if [[ $# -gt 1 ]]; then
        echo "Only one trash can path is acceptable"
        exit 1
    fi

    fullpath="$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
    if [ -f "${fullpath}" ]; then
        echo "${NAME}: cannot set directory '$1' as trash can: File exists"
        exit 1
    fi

    if [ ! -d "${fullpath}" ]; then
        echo "Target directory doesn't exist"
        echo -ne "Do you want to create this directory? [y/n]: \a"
        read reply

        if [ ! $reply = "y" -o ! $reply = "Y" ]; then
            exit 1
        fi

        mkdir -p "${fullpath}"
        if [ ! $? -eq 0 ]; then
            echo "mkdir ${fullpath} failed"
            exit 1
        fi
    fi

    TRASH_DIR="${fullpath}"
    LOG_FILE="${fullpath}/.log"
    touch "${LOG_FILE}"

    fullpath=${fullpath//\//\\\/} #replace all / with \/ in fullpath
    sed -i "0,/TRASH_DIR/{s/TRASH_DIR=.*/TRASH_DIR=\"${fullpath}\"/}" "$0"
}

clear_trash() {
    if [ $(uname -s) = "Darwin" ]; then
        echo "Clear trash is not permitted in Mac. Trash can is regularly cleared."
        exit 0
    fi

    echo -ne "Are you sure you want to clear trash? [y/n]:\a"
    read reply

    case $reply in
        'y'|'Y')
            for file in $(ls -A "${TRASH_DIR}"); do
                echo "Removing ${TRASH_DIR}/${file} foreverly."
                rm -rf "$TRASH_DIR/$file"
            done
            echo -ne "Do you want to clear all logs? [y/n]:\a"
            read reply
            if [ $reply = "y" -o $reply = "y" ]; then
                echo "clearing all logs"
                cat /dev/null > "${LOG_FILE}"
            fi
            echo "Done.";;
        'n'|'N') echo "Cancelling deleteing.";;
        *) echo "Unrecognized character.";;
    esac
}

force_delete() {
    if [ $# -eq 0 ]; then
        echo "${NAME}: missing operand"
        exit 0
    fi

    echo -ne "Are you sure you want to foreverly delete file[s]? [y/n]:\a"
    read reply

    case "$reply" in
        'y'|'Y')
            for file in $@; do
                rm -rf "${file}"
            done
            echo "Done.";;
        'n'|'N') echo "Cancelling deleteing.";;
        *) echo "Unrecognized character.";;
    esac
}

delete() {
    for file in $@; do
        debug "deleting ${file}"
        if [ ! -f "$file" -a ! -d "$file" ]
        then
            echo "${NAME}: cannot remove '$file': No such file or directory"
            continue
        fi

        # check if user want to move file larger than 2GB to trash
        if [ -f "$file" -a $(du -b "$file" | cut -f1) -gt 2147483648 ]; then
            echo "File '$file' size is larger than 2GB."
            echo -ne "Do you still want to move it to trash? [y/n]: \a"
            read reply

            if [ ! $reply = "y" -a ! $reply = "Y" ]; then
                echo "moving aborted"
                exit 0
            fi
        fi

        filename="$(basename "$file")"
        fullpath="$(cd "$(dirname "$file")"; pwd)/${filename}"
        now="$(date +%a%b%d%H%M%S%Y)"

        if [ -f "$TRASH_DIR/${filename}_${now}" -o -d "$TRASH_DIR/${filename}_${now}" ]; then
            sleep 1
            now="$(date +%a%b%d%H%M%S%Y)"
        fi

        mv $file "$TRASH_DIR/${filename}_${now}"
        debug "new filename ${filename}_${now}"
        if [ $? -eq 0 ]; then
            echo "${fullpath}_${now}" >> ${LOG_FILE}
        else echo -ne "mv $file to $TRASH_DIR/${filename} failed\a"
        fi
    done
}

restore() {
    if [ $# -eq 0 ]; then
        echo "${NAME}: restore missing operand"
        exit 1
    fi

    for file in $@; do
        filename="$(basename "$file")"
        fullpath="$(cd "$(dirname "$file")"; pwd)/${filename}"

        if [ $filename = $file ]; then #if only the basename is provided
            debug "match base name $filename"
            pattern="s/\(.*\)\/${filename}_\([a-zA-Z]\{3\}\)\([a-zA-Z]\{3\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{4\}\)/\1 \2 \3 \4 \5 \6 \7 \8/"
            logs=$(cat "${LOG_FILE}")
            candidates=()
            number=0

            for line in $logs; do
                res=( $(echo $line | sed "$pattern") )
                debug "match result: [${#res[@]}] ${res[@]}"
                if [ ${#res[@]} -gt 1 ]; then
                    echo -e "\e[0;33m[${number}]\e[0m ${res[0]}/${filename} \e[0;36m[${res[1]} ${res[2]} ${res[3]} ${res[4]}:${res[5]}:${res[6]} ${res[7]}]\e[0m"
                    candidates+=${res}
                    let number++
                fi
            done

            echo -n "enter the number of your target: "
            read reply

            if [ $reply -ge 0 -a $reply -lt $number ]; then
                let index=reply\*8
                fullpath="${candidates[$index]}/${filename}"
                if [ -f "${fullpath}" -o -d "${fullpath}" ]; then
                    echo "${NAME}: Restore target exists."
                    echo -ne "Do you want to override this file? [y/n]: \a"
                    read reply

                    if [ ! $reply = "y" -a ! $reply = "Y"]; then
                        exit 0
                    fi
                fi

                trash_file="${filename}_"
                for i in $(seq 1 7); do
                    trash_file+="${res[`expr index+${i}`]}"
                done
                
                if [ ! -f "${TRASH_DIR}/${trash_file}" -a ! -d "${TRASH_DIR}/${trash_file}" ]; then
                    error "Trash file ${trash_file} does not exist"
                    exit 1
                fi
                mv "${TRASH_DIR}/${trash_file}" "${fullpath}"
                
                sed -i "/${trash_file}/d" "${LOG_FILE}"
            else 
                echo -e "\e[0;31mrestore: reply '$reply' is out of bounds\e[0m"
                exit 1
            fi
        fi
    done
}

option="d"
args=()
declare -A -r funcs=(
    ["d"]="delete"
    ["h"]="usage"
    ["v"]="version"
    ["p"]="print_log"
    ["l"]="list"
    ["c"]="clear_trash"
    ["r"]="restore"
    ["t"]="set_trash"
    ["f"]="force_delete"
)

if [[ $# -eq 0 ]]; then
    echo "${NAME}: missing operand"
    echo "Try '${NAME} -h' for more information"
    exit 0
fi

# process arguments
while [[ $# -gt 0 ]]; do
    debug "arg $1"
    debug "args: ${args[@]}"
    case $1 in
        -h | -c | -f | -r | -v | -l | -p | -t)
            debug "calling ${funcs[$option]} ${args[@]}"
            if [ -z ${funcs[$option]} ]; then
                error "invalid option $option"
                exit 1
            fi
            ${funcs[$option]} ${args[@]}
            option=${1:1:1}
            args=()
            shift;;
        --help | --clear | --force | --restore | --version | --list | --print | --trash)
            debug "calling ${funcs[$option]} ${args[@]}"
            if [ -z ${funcs[$option]} ]; then
                error "invalid option $option"
                exit 1
            fi
            ${funcs[$option]} ${args[@]}
            option=${1:2:1}
            args=()
            shift;;
        -* | --*)
            echo "${NAME}: invalid option '$1'"
            echo "Try '${NAME} -h' for more informtion"
            exit 1;;
        *) args+=("$1"); shift;;
    esac
done

debug "calling ${funcs[$option]} ${args[@]}"
if [ -z ${funcs[$option]} ]; then
    error "invalid option $option"
    exit 1
fi
${funcs[$option]} ${args[@]}

标签:Shell,option,echo,file,fi,reply,rm,trash,回收站
From: https://www.cnblogs.com/kaleidopink/p/17632408.html

相关文章

  • layui-form 提交按钮不生效
    layui-form提交按钮不生效有时候layui-form不生效是因为div的层级关系错误造成的,比如把提交按钮放在了div的外部了;欢迎关注公-众-号【TaonyDaily】、留言、评论,一起学习。Don’treinventthewheel,librarycodeistheretohelp.文章来源:刘俊涛的博客若有帮助到您,欢迎点赞、......
  • [ABC134F] Permutation Oddness 题解
    题面定义一个\(1\simn\)的排列\(p\)的「怪异度」为\[\sum_{i=1}^n\left\lvertp_i-i\right\rvert\]求「怪异度」为\(k\)的\(1\simn\)的排列数,答案对\(10^9+7\)取模。题解考虑转化计算怪异度的过程,我们将值\(p_i\)排列在左侧,将下标\(i\)排列在右侧,构成一个......
  • [ABC134F] Permutation Oddness
    题目大意定义一个\(1\simn\)的排列\(p\)的「怪异度」为\[\sum_{i=1}^n|p_i-i|\]求「怪异度」为\(m\)的\(1\simn\)的排列数,答案对\(10^9+7\)取模。思路考虑把\(p_i\)和\(i\)看作小球与盒子,方便题意理解。考虑球与盒子的匹配。假设球在左侧,盒子在右侧,他们......
  • 解决Pycharm运行成功,但无法生成:pytest-html报告
    不生成报告的原因:用户习惯:使用者习惯于单独执行测试文件.py,调试测试用例;而编辑器为了方便用户执行测试用例,变调用pythontest来执行测试用例,这种情况下,执行的只是用例或者套件,不是整个文件,即main里面输出报告的语句没有执行,变不会生成测试报告;解决方法:如下图:1.全局执行;2.执......
  • Linux——shell变量及运算
    #注意等号两边不能有空格,命令才会有空格,像是dockerps,如果加空格,linux以为你写的是某种命令。#数字num=1#字符串str0=teststr1='test'str2="test"#字符串的三种声明方式是有区别的:#1.单引号中的内容回原样输出,不会转义,不会取值。#2.双引号中的内容输出,会转......
  • 云原生 AI 工程化实践之 FasterTransformer 加速 LLM 推理
    作者:颜廷帅(瀚廷)01背景OpenAI在3月15日发布了备受瞩目的GPT4,它在司法考试和程序编程领域的惊人表现让大家对大语言模型的热情达到了顶点。人们纷纷议论我们是否已经跨入通用人工智能的时代。与此同时,基于大语言模型的应用也如雨后春笋般出现,为我们带来了协同办公、客服对......
  • Winform-控件美化小技巧
    提供一些日常控件美化的小技巧,复杂需求则需要扩展控件。⭐圆角按钮,渐变色按钮1>从PPT中选择圆角长方形形状,填充颜色渐变色,右击另存为png图片;2>按钮的BackColor设置为透明,BackGroundImage设置为刚才的图片,LayOut设为Stretch;3>按钮的FlatStyle设置为Flat,FlatAppearance的Borde......
  • shell函数与数组
    目录shell函数与数组shell函数函数定义函数递归阶乘题目shell数组冒泡排序shell函数与数组shell函数函数定义将命令序列按格式写在一起可方便重复使用命令序列shell函数定义使用函数可以将大模块分割成小模块函数的组成:函数名、函数体[root@localhost~]#helpfuncti......
  • platform总线详解
    转载:手把手教Linux驱动10-platform总线详解-知乎(zhihu.com)platform总线是学习linux驱动必须要掌握的一个知识点。本文参考已发布:Linux3.14内核一、概念嵌入式系统中有很多的物理总线:I2c、SPI、USB、uart、PCIE、APB、AHBlinux从2.6起就加入了一套新的驱动管理和注册的......
  • mormot笔记一 连接数据库
    unitUnit1;interfaceusesWinapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.Grids,Vcl.StdCtrls,mormot.db.sql,mormot.db.core,mormot.db.sql.oledb,mormot.c......