【问题标题】:How to remove a set of files using a given string containing a wildcarded path in bash/zsh?如何在 bash/zsh 中使用包含通配符路径的给定字符串删除一组文件?
【发布时间】:2020-12-09 04:48:45
【问题描述】:

假设:假设我有一个通配符字符串变量,它表示一组以 .txt(包含空格)结尾的文件的路径:

a="/hello world/*.txt"

问题:我想在终端中使用 $rm$ 删除这些文件:

rm $a

当我执行上述命令时,出现以下错误:

rm: /hello world/*.txt: No such file or directory

以下相同:

rm "$a"

或者即使我转义了空格,我仍然会得到同样的错误。

问题:如何根据给定的可变格式通配符路径在 bash 中删除这些路径。

更多信息:

  • $- == 569JNRXZghiklms 的输出
  • 操作系统:Mac OS X 10.15.7
  • 我正在使用 zsh
  • 我的 bash --version 的输出:❯ bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19) Copyright (C) 2007 Free Software Foundation, Inc.

【问题讨论】:

  • echo $- 的输出添加到您的问题(无评论)。
  • 您要删除的文件的实际名称是什么?
  • @RamanSailopal 这不是文件。这是一个以 .txt 结尾的集合文件
  • @Cyrus 我用更多信息更新了问题

标签: macos zsh glob oh-my-zsh


【解决方案1】:

这在 zsh 中与其他 shell(例如 bash)有很大不同。在大多数 shell 中,如果你扩展一个变量而不用双引号括起来(比如rm $a),那么变量的值会受到分词(即分解成多个“词”)和通配符扩展的影响。然而,在 zsh 中,即使变量没有被双引号(至少在默认情况下),也不会对变量进行分词或通配符扩展。

在您的情况下,您需要进行通配符扩展,但分词(这会将其分成两个单独的项目,“/hello”和“world/*.txt”) .在 zsh 中,您可以明确要求使用 ~ 前缀完成通配符扩展:

rm ${~a}

您也可以使用setopt GLOB_SUBST,它会为所有后续变量(和命令)扩展打开通配符扩展。

如果您使用 bash 或其他类似的 shell,它会更复杂,因为它们没有自然的方法来进行通配符扩展而不进行分词。但是你可以改变分词的方式,所以它实际上并没有做任何事情:

saveIFS=$IFS
IFS=
rm $a
IFS=$saveIFS

IFS 是被视为单词分隔符的“空白”字符列表;当它是空字符串时,没有分隔符,所以不会发生实际的拆分。但是你应该确保之后将IFS恢复正常,否则你会得到奇怪的效果。

【讨论】:

  • 感谢您的回答。我正在寻找一种通用的方法。这是一个更大的脚本的一部分,我想将它作为包的一部分分发。这是rm ${~a} 通用解决方案吗?如果没有,您有什么建议吗?我不会想象删除一组文件会如此复杂,哈哈!
  • @linker 这取决于大局,但通常最好的答案是:不要将全局模式存储在变量中。通常将部分或全部固定部分存储在变量中并在使用它们时应用通配符部分(例如rm "$dir"/*."$ext")或立即将通配符扩展为匹配文件的数组(例如files=("/hello world"/*.txt)然后rm "${files[@]}"),或两者的混合(例如files=("$dir"/*."$ext"))。如果您在 bash 中编写脚本,请参阅 BashFAQ #20(尽管其中一些也适用于 zsh)。
猜你喜欢
  • 2014-10-20
  • 2020-07-27
  • 2013-08-19
  • 2020-09-17
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
相关资源
最近更新 更多