207

I do this in a script:

read direc <<< $(basename `pwd`)

and I get:

Syntax error: redirection unexpected

in an ubuntu machine

/bin/bash --version
GNU bash, version 4.0.33(1)-release (x86_64-pc-linux-gnu)

while I do not get this error in another suse machine:

/bin/bash --version
GNU bash, version 3.2.39(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

Why the error?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Open the way
  • 26,225
  • 51
  • 142
  • 196
  • FYI, context is very important. Find the name of program running a script try `grep PPid /proc/self/status | sed -E 's/^(PPid:\s*)(.*)$/\/proc\/\2\/exe/'`. to display what shell terminal is running try `echo $0` – dank8 May 25 '23 at 07:57

10 Answers10

367

Does your script reference /bin/bash or /bin/sh in its hash bang line? The default system shell in Ubuntu is dash, not bash, so if you have #!/bin/sh then your script will be using a different shell than you expect. Dash does not have the <<< redirection operator.

Make sure the shebang line is:

#!/bin/bash

or

#!/usr/bin/env bash

And run the script with:

$ ./script.sh

Do not run it with an explicit sh as that will ignore the shebang:

$ sh ./script.sh   # Don't do this!
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 4
    I have "#!/bin/bash" on top the sh file, but it still gives that error. It worked when used bash ./script.sh as @chris's said. – ibilgen Jan 14 '21 at 10:09
  • 8
    @ibilgen Are you running it with `sh ./script.sh`? Don't run scripts with an explicit shell. Just type the script name `./script.sh` so it can use the interpreter declared in the shebang line. – John Kugelman Jan 14 '21 at 10:13
  • Should I change default shell `dash` to `bash`? – kittygirl Jul 05 '21 at 13:23
  • @kittygirl I just changed from '/bin/sh' to '/bin/bash' and it worked!! – Tapan Hegde Sep 16 '21 at 06:31
  • No, don't change the default shell. This is a bug in the script / how the script is run. [Don't make global changes to fix a local problem.](https://devblogs.microsoft.com/oldnewthing/20081211-00/?p=19873) – John Kugelman Sep 16 '21 at 13:36
35

If you're using the following to run your script:

sudo sh ./script.sh

Then you'll want to use the following instead:

sudo bash ./script.sh

The reason for this is that Bash is not the default shell for Ubuntu. So, if you use "sh" then it will just use the default shell; which is actually Dash. This will happen regardless if you have #!/bin/bash at the top of your script. As a result, you will need to explicitly specify to use bash as shown above, and your script should run at expected.

Dash doesn't support redirects the same as Bash.

Chris Pietschmann
  • 29,502
  • 35
  • 121
  • 166
24

Docker:

I was getting this problem from my Dockerfile as I had:

RUN bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

However, according to this issue, it was solved:

The exec form makes it possible to avoid shell string munging, and to RUN commands using a base image that does not contain /bin/sh.

Note

To use a different shell, other than /bin/sh, use the exec form passing in the desired shell. For example,

RUN ["/bin/bash", "-c", "echo hello"]

Solution:

RUN ["/bin/bash", "-c", "bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)"]

Notice the quotes around each parameter.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131
  • This made it possible for me to get the [here-string](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Here-Strings) running inside a Dockerfile. That here-string was needed for saying "yes" (y) to an "overwrite question" (not important: it was for `ssh-keygen -q -t rsa <<< ""$'\n'"y"`, see https://stackoverflow.com/a/43235320/11154841). – questionto42 Mar 13 '21 at 12:02
  • 1
    Before RUN set `SHELL ["/bin/bash", "-c"]` and then all following RUN commands will be bash shell instead of sh. – Sam Gleske Nov 23 '22 at 05:20
12

You can get the output of that command and put it in a variable. then use heredoc. for example:

nc -l -p 80 <<< "tested like a charm";

can be written like:

nc -l -p 80 <<EOF
tested like a charm
EOF

and like this (this is what you want):

text="tested like a charm"
nc -l -p 80 <<EOF
$text
EOF

Practical example in busybox under docker container:

kasra@ubuntu:~$ docker run --rm -it busybox
/ # nc -l -p 80 <<< "tested like a charm";
sh: syntax error: unexpected redirection


/ # nc -l -p 80 <<EOL
> tested like a charm
> EOL
^Cpunt!       => socket listening, no errors. ^Cpunt! is result of CTRL+C signal.


/ # text="tested like a charm"
/ # nc -l -p 80 <<EOF
> $text
> EOF
^Cpunt!
  • 2
    ...or `echo 'text' | nc` which is even shorter. – phil294 Jun 08 '19 at 12:59
  • Thanks for the work-around. On MacOS you have to do `\. /dev/stdin <<< "$(wget -qO- https://...myscript.sh)"` to successfully source a remote script with the current function arguments and import its functions to the local terminal. Your solution made it POSIX compliant. – Martin Braun Feb 23 '23 at 02:44
2

do it the simpler way,

direc=$(basename `pwd`)

Or use the shell

$ direc=${PWD##*/}
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
1

On my machine, if I run a script directly, the default is bash.

If I run it with sudo, the default is sh.

That’s why I was hitting this problem when I used sudo.

Milo
  • 3,365
  • 9
  • 30
  • 44
1

Another reason to the error may be if you are running a cron job that updates a subversion working copy and then has attempted to run a versioned script that was in a conflicted state after the update...

Motin
  • 4,853
  • 4
  • 44
  • 51
0

In my case error is because i have put ">>" twice

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> >> $LOG_PATH

i just correct it as

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> $LOG_PATH
luk2302
  • 55,258
  • 23
  • 97
  • 137
Mansur Ul Hasan
  • 2,898
  • 27
  • 24
0

Before running the script, you should check first line of the shell script for the interpreter.

Eg: if scripts starts with /bin/bash , run the script using the below command "bash script_name.sh"

if script starts with /bin/sh, run the script using the below command "sh script_name.sh"

./sample.sh - This will detect the interpreter from the first line of the script and run.

Different Linux distributions having different shells as default.

Sijeesh
  • 197
  • 2
  • 9
  • 2
    Though we thank you for your answer, it would be better if it provided additional value on top of the other answers. In this case, your answer does not provide additional value, since another user already posted that solution. If a previous answer was helpful to you, you should vote it up instead of repeating the same information. – Toby Speight Jan 23 '18 at 11:00
  • Don't you think that I explained the solution here with an example? – Sijeesh Feb 02 '18 at 09:00
  • 2
    Is there anything here that isn't adequately covered in [John Kugelman's answer](/a/2462357) written 8 years ago? – Toby Speight Feb 02 '18 at 09:10
0

Point 1: #!/bin/bash
Point 2: Make sure your file have suitable permissions (for a sample sh file, chmod 777 test.sh)
Point 3: ./test.sh, don't use sh test.sh

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 24 '23 at 15:19
  • Whatever you are hoping to accomplish, **`chmod 777` is *wrong* and *dangerous.*** You absolutely do not want to grant write access to executable or system files to all users under any circumstances. You will want to revert to sane permissions ASAP (for your use case, probably chmod 755) and learn about the Unix permissions model before you try to use it again. If this happened on a system with Internet access, check whether an intruder could have exploited this to escalate their privileges. – tripleee May 25 '23 at 17:50