为 rm 命令创建别名

为 rm 命令创建别名

为 rm 命令创建别名,以便在rm执行命令时首先将文件复制到/tmp/recycle_bin,然后删除该文件。但我在这个过程中遇到了问题。

我执行的步骤:

  1. 我在~/.bashrc文件中写了以下命令:

    alias rm='cp $@ /tmp/recycle_bin && rm $@'
    
  2. 使用以下命令执行它:

    . ~/.bashrc
    
  3. 打开新终端并执行以下命令:

    rm "/home/XXXXX/My_Programs/test_method.py"
    cp: missing destination file operand after '/tmp/recycle_bin'** got this error message 
    

需要了解:

  1. 即使参数作为我要删除的文件传递给 rm 命令。为什么我在之后收到错误**缺少目标文件操作数/tmp/recycle_bin

  2. 别名命令中的变量$@未填充?这种情况如何调试并解决?

答案1

别名不能$@像这样接受参数并使用它们来访问它们。

别名扩展bash是简单的文本替换。如果有alias rm ='something something',那么 usingrm file1 file2将执行

something something file1 file2

如果包含别名$@,则将使用命令行参数进行扩展贝壳,不是别名。

在您的情况下,假设 shell 的命令行参数列表为空,则别名

alias rm='cp $@ /tmp/recycle_bin && rm $@'

将执行为

cp /tmp/recycle_bin && rm file1 file2

当调用为rm file1 file2.该cp实用程序会抱怨只有一个操作数。


您可以使用 shell 函数来代替:

rm () {
    cp -- "$@" "${TMPDIR:-/tmp}/recycle_bin" &&
    command rm -- "$@"
}

这会将指定的文件复制到$TMPDIR/recycle_bin(或者/tmp/recycle_bin如果TMPDIR未设置或为空),然后删除这些文件。该command命令用于不导致无限递归。需要--将所有参数视为文件名而不是选项。另请注意,引号很重要,以便文件名不会在空格上分割,并且参数中的文件名通配模式不会拾取您想要的文件。想要删除。

效率更高一点(cp+ rm== mv):

rm () {
    mv -- "$@" "${TMPDIR:-/tmp}/recycle_bin"
}

更安全一点(如果不存在则创建回收站):

rm () {
    mkdir -p "${TMPDIR:-/tmp}/recycle_bin" &&
    mv -- "$@" "${TMPDIR:-/tmp}/recycle_bin"
}

使用 GNU 甚至更安全mv(如果发生名称冲突,则在回收站中创建备份):

rm () {
    mkdir -p "${TMPDIR:-/tmp}/recycle_bin" &&
    mv -b -- "$@" "${TMPDIR:-/tmp}/recycle_bin"
}

对于仅别名(和仅 GNU)的变体,请参阅“不使用函数创建回收站功能”。

答案2

Bash 和大多数 Bourne 派生的 shell 不支持参数化别名。

你不能这样做事。

一种工作方法是定义一个扩展 do 的别名:

sh -c 'cp -- "$@" /tmp/recycle_bin && rm -- "$@"' sh

这会产生以下命令:

myrm='sh -c '\''cp -- "$@" /tmp/recycle_bin && rm -- "$@"'\'' sh'

请注意,如果您使用最新版本的 Bourne Shell (bosh),则无需创建新 shell 进程的开销即可完成此操作。该 shell 包含一个内置命令dosh,其作用类似于调用中的一行脚本sh -c。可参数化别名的概念是由前 AT&T 员工于 1980 年发明的,并在名为 的实时 UNIX 克隆中实现UNOS

bosh你可以使用:

myrm='dosh '\''cp -- "$@" /tmp/recycle_bin && rm -- "$@"'\'' myrm'

顺便说一句:Bourne Shell 可以帮助您在原始模式下键入别名命令,并自动为单引号字符创建所需的转义序列。我自己并没有用转义符编写这个丑陋的命令行,而是让我们bosh从上面的原始命令行创建它。

相关内容