使用 asterix 时在 bash 脚本中找不到文件夹

使用 asterix 时在 bash 脚本中找不到文件夹

我正在尝试从 Mac 上的终端(在 bash 上运行)删除几个子文件夹。子文件夹以相同的两个字母“na”开头,我编写了如下代码:

       if [[ -d "$base/${subject}/${session}/"na* ]]; then
echo "removing na folder from all folders"
rm -rf "$base/${subject}/${session}/"na*

我尝试了各种不同的方法来编写它(使用括号内和括号外的 *、括号内和括号外的 na 等等)。当我运行代码时,它不会回显消息,因此找不到文件夹。在阅读了类似问题的答案后(删除 Mac OS X 上不支持通配符的 rm 命令) 我做了一个“while 循环”来确保它不会在一个文件夹后停止,但问题仍然存在,即“na*”文件夹首先找不到。如果我用一个确切的子文件夹名称替换 *,它就可以工作了。但这相当不方便。

希望有人能帮忙!


编辑:

谢谢你们两位的回复。Maciorowski 的代码片段起了作用,解决了问题!也非常感谢你们的教育性回答。不知道 [[ 和 * 的警告。

答案1

[[和之间的单词]]不经过 […] 文件名扩展。您的第一个*没有展开。显然没有名为(字面上)的子目录na*,测试失败,因此rm未执行。

如果rm要进行的话,*会先进行扩展。

诊断另一个答案“[第一个]na*将扩展为多个名称”是错误的。na*它根本没有扩展。

如果你使用[ -d …/na* ]而不是[[ -d …/na* ]]那么na*将会被扩展和然后您可能会得到几个路径名([会打印错误)。[并且[[不等同

rm -rf "$base/${subject}/${session}/"na*有点缺陷。由于rm不是 Bash 的内置命令,因此扩展后的行可能太长,你可能会得到Argument list too long。链接指向一个包含两种不同解决方案的答案:带有forfind。针对您的情况量身定制的解决方案示例for可能是:

( shopt -s nullglob
mark=
for d in "$base/$subject/$session/"na*/; do
  [ -z "$mark" ] && { mark=1; echo "Removing \`na*' directories from \`$base/$subject/$session/'" >&2; }
  echo rm -rf "$d"
done )

(故障安全,试运行。如果结果看起来不错,则替换echo rm为。)rm

笔记:

  • 尾随的反斜杠na*/使模式仅匹配目录。
  • shopt -s nullglob是万一na*/匹配零个目录。通常情况下,匹配零个的模式将保持原样;当nullglob它扩展为零个单词时,我们的循环就变成for d in; do …,并且其主体执行零次。
  • 您的原始消息 ( removing na folder from all folders) 具有误导性。我的代码和您的原始代码都没有尝试“从文件夹中删除文件夹”。$base/$subject/$session/不能是“文件夹s“。我更改了信息。
  • 我操纵mark仅在需要时回显消息,并且仅回显一次。看来这就是你想要的。
  • 对我来说,该消息看起来具有“诊断性”,因此>&2
  • 该代码片段在子 shell 中运行。要点是nullglobmarkd是 shubshel​​l 本地的,不会影响任何其他内容。

答案2

您期望na*会扩展为多个名称,但据我所知,-d测试只接受一个参数。此外,正如另一个答案所指出的那样,内部没有发生任何扩展[[ ]]

一种解决方案是迭代find

find "$base/${subject}/${session}" -mindepth 1 -maxdepth 1 -type d -name "na*" -exec rm -rf {} \;

如果你想从基础开始递归删除树结构中的所有“na*”文件夹:

find "$base" -type d -name "na*" -exec rm -rf {} \;

相关内容