My friend asked me why this two simple script are not working in both shells:
Test File "abc.txt":
aaa 111 bbb 111 ccc 111 ddd
Script #1 (a):
#!/bin/sh while read -r line ; do echo "Processing $line" done < <(grep 111 abc.txt)
./a: line 4: syntax error near unexpected token `<' ./a: line 4: `done < <(grep 111 abc.txt)'
Script #2 (b):
#!/bin/bash while read -r line ; do echo "Processing $line" done < <(grep 111 abc.txt)
Processing 111 Processing 111 Processing 111
I checked bash and sh on my machine and if I understand this correct this is the same thing.
/bin/sh is just a link to /bin/bash:
-rwxr-xr-x 1 root root 938736 May 10 2012 bash lrwxrwxrwx. 1 root root 4 Feb 13 10:20 sh -> bash
Can someone explain me where is the difference?
When invoked as sh, bash enters posix mode after the startup files are read.
So you can not use bash features when run your script with
It's because Bash behaves differently when
When Bash starts in SH compatiblity mode, it tries to mimic the startup behaviour of historical versions of
shas closely as possible, while conforming to the POSIX® standard as well. The profile files read are
~/.profile, if it's a login shell.
If it's not a login shell, the environment variable ENV is evaluated and the resulting filename is taken as name of the startup file.
After the startup files are read, Bash enters the POSIX(r) compatiblity mode (for running, not for starting!).
Bash starts in
shcompatiblity mode when:
- the base filename in
sh(Attention dear uber-clever Linux users…
/bin/shmay be linked to
/bin/bash, but that doesn't mean it acts like
More information can be found at the Bash Reference Manual: Bash POSIX Mode, specifically:
- Process substitution is not available.
which is why your
sh script is failing, as the
<(..) syntax is using process substitution.