与输出重定向一起使用时,shell 脚本不会解释通配符

tat*_*tsu 3 shell scripting bash shell-script wildcards

假设我有两个脚本:

  • 脚本1.sh:

    #!/bin/bash
    version=2.6
    log_file="$HOME/log-file-version-$version.log"
    
    touch $log_file &>/dev/null
    
    echo "log to my log file from script 1" >> $HOME/log-file-version-?.?.log
    
    gnome-terminal --tab --active --title="script2" --  sh script2.sh
    
    Run Code Online (Sandbox Code Playgroud)
  • 脚本2.sh:

    #!/bin/bash
    
    echo "log to my log file from script 2" >> $HOME/log-file-version-?.?.log
    
    Run Code Online (Sandbox Code Playgroud)

我跑script1.sh

我家中有两个日志文件:

log-file-version-2.6.log
log-file-version-?.?.log
Run Code Online (Sandbox Code Playgroud)

log-file-version-2.6.log 包含:

从脚本 1 登录到我的日志文件

log-file-version-?.?.log 包含:

log to my log file from script 2

which means that in script 1 the wildcards from line 7 (>> $HOME/log-file-version-?.?.log) were correctly interpreted, but when a script is run with sh these wildcards don't work.

Why is that and how can I fix this?

I need to use wildcards because I don't want to be passing arguments from shell script to shell script and I want them to be self-sufficient.

I'm using Ubuntu and running these scripts from the default terminal which is gnome-terminal.

gle*_*man 7

The bash manual has this to say in the 3.6 Redirections section:

The word following the redirection operator in the following descriptions, unless otherwise noted, is subjected to brace expansion, tilde expansion, parameter expansion, command substitution, arithmetic expansion, quote removal, filename expansion, and word splitting. If it expands to more than one word, Bash reports an error.

sh does not do that: from the POSIX shell specification

如果重定向运算符是“ <<”或“ <<-”,[...]。对于其他重定向操作符,跟在重定向操作符后面的单词应进行波浪号扩展、参数扩展、命令替换、算术扩展和引号删除。非交互式 shell 不得对单词执行路径名扩展;一个交互式 shell 可以执行它,但只有在扩展会导致一个单词时才会这样做。

$ dash
$ echo foo > *
$ ls
'*'  README.md  ...
Run Code Online (Sandbox Code Playgroud)
$ bash
$ echo bar >> *
bash: *: ambiguous redirect
Run Code Online (Sandbox Code Playgroud)

  • @tatsu 使用`bash` 重定向到文件glob 仅适用于_知道_ glob 将始终扩展为单个文件的情况。理想情况下,您应该在命令行上将正确的文件名传递给脚本(在这种情况下,使用`bash` 或`sh` 并不重要)。 (2认同)