0

我对编写 bash 脚本非常陌生。这个问题可能很基础,但我还没有找到明确的答案。我正在 Windows 10 上安装 Ubuntu 子系统。

我正在运行一个包含以下条件的脚本:

if [ -z "$date1" ]; then
    date1=$(head -n 1 "$dir"/*.txt | sed "s/^[^0-9]*//g" | date +%Y%m%d -f - 2>/dev/null)
fi

当它遇到dir没有 .txt 文件的目录(变量)时会遇到问题,但我不太了解问题的本质。我确实知道问题出在head命令中,至少部分是这样。我没有收到错误,脚本只是在到达没有 .txt 文件的目录时停止。我希望脚本继续前进。如果我在终端中单独运行该行(没有条件),我会收到一个No such file or directory错误,这是有道理的。真正让我感到困惑的是,如果我在通配符部分 (ie '*.txt') 周围加上引号(单引号或双引号),那么脚本会吐出head错误并继续前进。我有限且可能不正确的理解是,这种情况下的引号意味着程序不再处理*作为通配符,只需按文字名称查找文件*.txt。但我认为,当*bash 解释它时,它首先寻找任何可能的扩展,然后如果找不到,则尝试字面解释。那么为什么脚本会在一种情况下而不是另一种情况下停止。两者都不应该No such file or directory像在脚本之外运行时那样简单地给我同样的错误吗?

我还要提到该脚本包括前面的条件,这些条件首先查找 .docx 文件,并且仅在没有 .docx 文件时才移动到 .txt 文件。它可以很好地处理没有 .docx 文件的情况,尽管该管道中的第一个命令是unzip而不是.docx 文件head这个问题似乎很相关,但是由于脚本能够在通配符周围有引号时继续前进,并且由于它在没有 .docx 文件的类似情况下继续前进,所以我想了解这里的问题和修复它的最佳方法。

我感谢您的帮助。

4

1 回答 1

1

在引号中, *不会扩展并且将是文字*字符。

另一方面,当*尝试扩展但失败时,会发生以下三种情况之一:

  • 它被逐字解释为字符串*.txt(加上任何$dir/扩展为)
    • 您可以使用 强制执行此行为shopt -u nullglob,这应该是默认设置。
  • 它扩展为空,使字符串$dir/*.txt等于空字符串
    • 您可以使用 强制执行此行为shopt -s nullglob
  • 它引发了一个错误
    • shopt -s failglob您可以使用(或使用 关闭它)强制执行此行为shopt -u failglob

例子:

bash-5.0# shopt -s | grep glob
globasciiranges on
bash-5.0# echo *.asdf
*.asdf
bash-5.0# shopt -s nullglob
bash-5.0# echo *.asdf

bash-5.0# shopt -u nullglob
bash-5.0# echo *.asdf
*.asdf
bash-5.0# shopt -s failglob
bash-5.0# echo *.asdf
bash: no match: *.asdf
bash-5.0# shopt -s | grep glob
failglob        on
globasciiranges on

当 glob 扩展为空字符串时,head除非您输入 stdin,否则将永远挂起(head $(echo '') | cat除非您键入,否则永远不会完成)

于 2021-03-03T01:55:53.503 回答