【问题标题】:How to capture "*" as argument to bash function and use in a comparison如何捕获“*”作为 bash 函数的参数并在比较中使用
【发布时间】:2016-12-04 13:06:15
【问题描述】:

如果我输入rm *,我想让bash 运行rm -i *,否则运行常规rm。重要的是,我不想每次使用诸如rm part* 之类的通配符时都运行rm -i。这是我能想到的:

rm ()
{
    if [ "$1" == "*" ]; then
        rm -i *
    else
        rm $1
    fi
}

但我知道这会失败。我知道我想要的比较是^*$,但是我不知道如何实现。

【问题讨论】:

  • 当你的rm函数被执行时,*已经被扩展了。
  • 问题是rm 没有得到* 作为参数;它获取 shell 将 * 扩展为参数的一长串文件。
  • GNU rm 有一个 -I 选项,仅在删除超过 3 个文件时才会提示您。
  • 顺便说一句,== 实际上并不能保证在符合 POSIX 测试的[ ] 内工作;参见pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html,它指定=(只有一个字符)作为字符串比较运算符。现在,bash 通过使== 作为选项可用来扩展标准,但是如果您想明确表示您依赖于 bash 扩展,最好改用[[ ]]
  • 是的,我需要处理我的 shell 脚本一致性。仍然是一个菜鸟/黑客。

标签: regex bash wildcard rm


【解决方案1】:

如果没有你的 shell 的配合,你的命令是否被通配符调用是字面上不可能

当您调用rm *(与任何其他命令一样)时,* 将替换为调用前的文件名列表。因此,在命令内部时,为其赋予通配符的信息不再存在:$1$2 等已被替换为通配符扩展为的名称列表。


也就是说,既然我们是一个shell函数,那么我们shell的配合其实是可以的:

rm() {
  local cmd
  read -r _ cmd < <(HISTTIMEFORMAT=''; history 1)
  if [[ $cmd = "rm *" ]]; then
    command rm -i "$@"
  else
    command rm "$@"
  fi
}

这是如何工作的?

  • history 1 返回 shell 历史中最新的命令(前面有一个数字)。
  • read -r _ cmd 将该数字读入变量_,命令行的其余部分读入变量cmd
  • [[ $cmd = "rm *" ]] 将命令与该精确字符串进行比较
  • command rm ... 运行 external rm 命令,避免再次递归回我们的函数。

【讨论】:

  • 这可能不适用于某些情况。我的外壳中有export HISTTIMEFORMAT="[%F %T] ",但它失败了。可能条件可以更改为[[ $cmd == *"rm *" ]]
  • 不,我不是那个意思。在当前形式中,这个函数没有运行rm -i ...,因为我的.bashrc 中有export HISTTIMEFORMAT="[%F %T] ",这导致history 1 输出49370 [2016-07-29 15:42:52] rm *。这就是为什么我建议[[ $cmd == *"rm *" ]] 可能会起作用
  • facepalm -- 我错过了*"rm *" 固定在最后。是的,这很有意义。
  • @anubhava, ...虽然在考虑中,我认为在子外壳中清除 HISTTIMEFORMAT 是更简单的更改。
  • 是的,确实解除 HISTTIMEFORMAT 确实对我有用。
【解决方案2】:

既然不知道是否有通配符,为什么不检查参数的数量呢?

例如:

#!/bin/bash
rm () {
    if [ "$#" -gt 1 ]; then
       echo command rm -i "$@"
    else
       echo command rm "$@"
    fi
}
rm a b c
rm a

【讨论】:

  • ...但您不知道您是否收到a,因为这是* 的评估结果,或者a,因为这是用户传递的内容。
  • @CharlesDuffy:确实如此。但我认为用例是警告是否要删除多个文件,因此它可能是 OP 的有效替代方案。
  • 我非常喜欢该解决方案的优雅。它实际上触及了问题的核心——阻止我删除多个文件(或我放入的任何数字)。但我认为实际捕获命令总体上更安全。干得好!
  • OP 说“重要的是,我不想每次使用诸如rm part* 之类的通配符时都运行rm -i”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
  • 2014-02-03
  • 2017-12-27
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多