3

I have a shell script which uses process substitution

The script is:

 #!/bin/bash while read line do echo "$line" done < <( grep "^abcd$" file.txt ) 

When I run the script using sh file.sh I get the following output

$sh file.sh file.sh: line 5: syntax error near unexpected token `<' file.sh: line 5: `done < <( grep "^abcd$" file.txt )' 

When I run the script using bash file.sh, the script works.

Interestingly, sh is a soft-link mapped to /bin/bash.

$ which bash /bin/bash $ which sh /usr/bin/sh $ ls -l /usr/bin/sh lrwxrwxrwx 1 root root 9 Jul 23 2012 /usr/bin/sh -> /bin/bash $ ls -l /bin/bash -rwxr-xr-x 1 root root 648016 Jul 12 2012 /bin/bash 

I tested to make sure symbolic links are being followed in my shell using the following:

$ ./a.out hello world $ ln -s a.out a.link $ ./a.link hello world $ ls -l a.out -rwx--x--x 1 xxxx xxxx 16614 Dec 27 19:53 a.out $ ls -l a.link lrwxrwxrwx 1 xxxx xxxx 5 May 14 14:12 a.link -> a.out 

I am unable to understand why sh file.sh does not execute as /bin/bash file.sh since sh is a symbolic link to /bin/bash.

Any insights will be much appreciated. Thanks.

8
  • I guess you aren't executing bash because /bin comes before /usr/bin in $PATH and there is a sh program in /bin. Commented May 14, 2013 at 19:32
  • but which sh shows /bin/sh which points to /bin/bash...thus should not be /bin/bash be executed? Thanks Commented May 14, 2013 at 19:34
  • Hmm. But it's obvious sh and bash dont execute the same program. Commented May 14, 2013 at 19:38
  • 2
    It's not a problem. bash is executed, but it detects that it is started using the name sh and behaves accordingly: as a (nearly) strictly compliant POSIX shell. One consequence of that is that it does not recognize process substitutions. Commented May 14, 2013 at 19:55
  • 1
    @Lennart Please see William's answer below. When bash is executed as sh, it enters in POSIX mode...and does not run in normal bash mode. So if I execute as bash --posix file.sh, I get the same error. Thanks for your time. Commented May 14, 2013 at 19:56

1 Answer 1

4

When invoked as sh, bash enters posix mode after the startup files are read. Process substitution is not recognized in posix mode. According to posix, <(foo) should direct input from the file named (foo). (Well, that is, according to my reading of the standard. The grammar is ambiguous in many places.)

EDIT: From the bash manual:

The following list is what’s changed when ‘POSIX mode’ is in effect: ... Process substitution is not available. 
Sign up to request clarification or add additional context in comments.

4 Comments

Since sh is a symblink to bash (see the output of which and ls -l in my question), should not executing sh command invoke bash? I am not concerned about why sh file.sh gives error, but why sh file.sh is not equivalent to bash file.sh when sh is symblink to bash. Thanks.
@Bill sh file.sh gives an error because sh file.sh is not equivalent to bash file.sh. bash simply parses and executes the same script differently when it is invoked as sh instead of bash.
@WilliamPursell since sh is symlink to bash, should not bash be executed? thats the meaning of symlinks, if I am not wrong...Please see the output of which and ls -l in the question. Thanks
@Bill bash is executed. From the bash man page: " If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well."

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.