【问题标题】:expand wildcards in string variable在字符串变量中展开通配符
【发布时间】:2017-07-05 09:10:16
【问题描述】:

我正在从包含应该删除的文件和文件夹的黑名单文件中读取字符串。它适用于简单的文件名,但不适用于通配符。

例如如果我在 shell 上键入 rm -rf !(abc|def),它会删除除这两个文件之外的所有文件。将此字符串 !(abc|def) 放入黑名单时不起作用,因为该字符串未得到评估。

所以我尝试使用eval,但它没有按预期工作。

#!/bin/bash
# test pattern (normally read from blacklist file)
LINE="!(abc|def)"

# output string
echo "$LINE"

# try to expand this wildcards
eval "ls $LINE"

# try with subshell
( ls $LINE )

我怎样才能使它工作?

【问题讨论】:

  • `我正在从黑名单文件中读取字符串`:如何?您的代码没有显示这部分。
  • 你最好将 find 与 -regex 和 -delete 一起使用。
  • sjsam,我没有展示这部分,因为它与我的问题无关。我准备了一个精简的脚本,以便更容易重现问题。

标签: bash wildcard expansion


【解决方案1】:

很可能,extglob shell 选项对于非交互式 shell(如脚本运行的那个)已关闭。

你必须改变一些事情:

#!/bin/bash

# Turn on extglob shell option
shopt -s extglob

line='!(abc|def)'

echo "$line"

# Quoting suppresses glob expansion; this will not work
ls "$line"

# Unquoted: works!
ls $line

你必须

  • 打开extglob shell 选项
  • 使用$line unquoted:引用抑制全局扩展,这几乎总是需要,但不是这里

请注意,我使用小写的变量名。大写是为shell和环境变量保留的;使用小写字母可降低名称冲突的可能性(参见POSIX spec,第四段)。

另外,这里不需要eval

【讨论】:

  • 这可能会解决问题。但是,我很想知道操作是如何从黑名单文件中读取这些文件名的。 :)
  • @sjsam 是的,很可能是 X/Y 问题;)
  • 您可能想提一下,您可以扩展为 Bash 数组变量(例如 a=($line) 或使用 for 进行迭代(可移植),但要避免使用 eval 和 subshel​​l 方法,如问题,这会丢失单个文件名的标识。在使用-- 方面可能也值得一些指导,以避免名称看起来像命令选项的问题。
  • 您可能还想通过设置IFS= 来禁用分词
  • @chepner 我同意所有这些都是有效的观点。我的回答解决了问题中显示的具体问题,因为问题没有显示如何读取模式。虽然我完全赞成在答案中展示最佳做法,但我不认为每个答案都可以包罗万象,并指出如果问题甚至没有提及它们可能会出错的事情。
猜你喜欢
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-29
  • 2019-02-08
  • 2011-11-16
  • 2016-08-22
相关资源
最近更新 更多