bash 脚本中通配符的停滞问题
Stalling problem with wildcard in bash script
我对编写 bash 脚本还很陌生。这个问题可能非常基本,但我还没有找到明确的答案。我正在 Windows 10.
上安装 Ubuntu 子系统
我正在 运行ning 一个包含以下条件的脚本:
if [ -z "$date1" ]; then
date1=$(head -n 1 "$dir"/*.txt | sed "s/^[^0-9]*//g" | date +%Y%m%d -f - 2>/dev/null)
fi
当遇到没有 .txt 文件的目录(dir
变量)时,它 运行 会遇到问题,但我不太了解问题的本质。我知道问题出在 head
命令中,至少部分是这样。我没有收到错误,脚本只是在到达没有 .txt 文件的目录时停止。我希望脚本继续前进。如果我在终端中 运行 行本身(没有条件),我会得到一个 No such file or directory
错误,这是有道理的。真正让我感到困惑的是,如果我在通配符部分(即 '*.txt'
)周围放置引号(单引号或双引号),那么脚本会吐出 head
错误并继续前进。我有限且可能不正确的理解是,在这种情况下,引号意味着程序不再将 *
视为通配符,而只是通过字面名称 *.txt
查找文件。但我认为当 *
被 bash 解释时,它首先寻找任何可能的扩展,然后如果找到 none 则尝试字面解释。那么为什么脚本在一种情况下停滞而不是另一种情况。两者不应该像在脚本外 运行 时那样简单地给我相同的 No such file or directory
错误吗?
我还要提到的是,该脚本包括先查找 .docx 文件并仅在没有 .docx 文件时才移动到 .txt 文件的前面的条件。它可以很好地处理没有 .docx 文件的情况,尽管该管道中的第一个命令是 unzip
而不是 head
。 问题似乎是相关的,但是由于当通配符周围有引号时脚本能够继续运行,并且由于它在没有 .docx 文件的类似情况下继续运行,我想了解问题所在在这里和修复它的最佳方法。
感谢您的帮助。
在引号中,*
不会展开,而是文字 *
字符。
另一方面,当 *
尝试扩展失败时,会发生以下三种情况之一:
- 它按字面解释为字符串
*.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
将永远挂起,除非您输入标准输入(head $(echo '') | cat
将永远不会完成,除非您输入)
我对编写 bash 脚本还很陌生。这个问题可能非常基本,但我还没有找到明确的答案。我正在 Windows 10.
上安装 Ubuntu 子系统我正在 运行ning 一个包含以下条件的脚本:
if [ -z "$date1" ]; then
date1=$(head -n 1 "$dir"/*.txt | sed "s/^[^0-9]*//g" | date +%Y%m%d -f - 2>/dev/null)
fi
当遇到没有 .txt 文件的目录(dir
变量)时,它 运行 会遇到问题,但我不太了解问题的本质。我知道问题出在 head
命令中,至少部分是这样。我没有收到错误,脚本只是在到达没有 .txt 文件的目录时停止。我希望脚本继续前进。如果我在终端中 运行 行本身(没有条件),我会得到一个 No such file or directory
错误,这是有道理的。真正让我感到困惑的是,如果我在通配符部分(即 '*.txt'
)周围放置引号(单引号或双引号),那么脚本会吐出 head
错误并继续前进。我有限且可能不正确的理解是,在这种情况下,引号意味着程序不再将 *
视为通配符,而只是通过字面名称 *.txt
查找文件。但我认为当 *
被 bash 解释时,它首先寻找任何可能的扩展,然后如果找到 none 则尝试字面解释。那么为什么脚本在一种情况下停滞而不是另一种情况。两者不应该像在脚本外 运行 时那样简单地给我相同的 No such file or directory
错误吗?
我还要提到的是,该脚本包括先查找 .docx 文件并仅在没有 .docx 文件时才移动到 .txt 文件的前面的条件。它可以很好地处理没有 .docx 文件的情况,尽管该管道中的第一个命令是 unzip
而不是 head
。
感谢您的帮助。
在引号中,*
不会展开,而是文字 *
字符。
另一方面,当 *
尝试扩展失败时,会发生以下三种情况之一:
- 它按字面解释为字符串
*.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
将永远挂起,除非您输入标准输入(head $(echo '') | cat
将永远不会完成,除非您输入)