2

Say I have two scripts:

  • script1.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
    
  • script2.sh:

    #!/bin/bash
    
    echo "log to my log file from script 2" >> $HOME/log-file-version-?.?.log
    

I run script1.sh.

I'm left with two log files in my home:

log-file-version-2.6.log
log-file-version-?.?.log

log-file-version-2.6.log contains:

log to my log file from script 1

log-file-version-?.?.log contains:

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.

  • Upvoted because the question is clear and reproducible -- and I learned something new about the differences in how POSIX-compliant shells behave. – Anthony G - justice for Monica Jul 19 at 23:03
2

i believe it is because the ? wildcard is a bash feature, not shell (sh).

Try running

gnome-terminal --tab --active --title="script2" -- bash script2.sh

When you run ./script1.sh it defaults to using bash as instructed on the 1st line. However, when you run sh script2.sh you use the shell to interpret the commands, and it ignores the recommendation from the 1st line.

  • 3
    the ? is and always was a sh feature. It's a bash and only bash feature to expand globs (any globs) in redirections, as explained in the other answer. This answer is wrong and should be deleted. – Uncle Billy Jul 19 at 23:20
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

If the redirection operator is "<<" or "<<-", [...]. For the other redirection operators, the word that follows the redirection operator shall be subjected to tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal. Pathname expansion shall not be performed on the word by a non-interactive shell; an interactive shell may perform it, but shall do so only when the expansion would result in one word.

$ dash
$ echo foo > *
$ ls
'*'  README.md  ...
$ bash
$ echo bar >> *
bash: *: ambiguous redirect
  • thank you! much clearer. although I had no particular use for sh if bash could accomplish the same. I just forgot about bash. do you think sh is more appropriate here? – tatsu Jul 19 at 12:27
  • 1
    Why are you putting wildcards on the RHS of a redirection? Why don't you already know the filename? What if there are more than one matching file? – glenn jackman Jul 19 at 12:28
  • 2
    @tatsu Redirecting to a file glob with bash is only appropriate if you know that the glob will expand to a single file, always. Ideally, you should hand the correct filename to the script on the command line instead (in which case it does not matter if you use bash or sh). – Kusalananda Jul 19 at 12:29
  • 1
    This is a much better answer as it explains the underlying reason why the behaviour of sh (actually dash in this case) differs from that of bash. – Anthony G - justice for Monica Jul 19 at 12:30
  • actually I just wanted to know why that wasn't working, it was bugging me, but of course the parent script knows the full name and can pass that as a variable, which (of course) is more robust, I guess being in the middle of testing something and lazyness got the better of me but now I'll probably pass it as a variable. – tatsu Jul 19 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.