Executing a shell script with code accepted using I/O indirection - shell

I am trying to execute a script like this, accepting script using indirection
sh <<EOT
for str in `cat test`
do
echo $str
done
EOT
The file "test" has contents
a
b
c
It gives below error.
sh: line 2: syntax error near unexpected token `b'
sh: line 2: `b'
Can anyone clarify ?. My aim is to execute the script like above instead of creating a shell script file script.sh and executing it (which works fine)

Your outer shell is interpolating the HEREDOC. To prevent that, quote the delimiter:
sh << 'EOT'
To clarify, what you have is equivalent to:
sh <<EOT
for str in a
b
c
do
echo
done
EOT
which makes the syntax error fairly obvious.

Related

Executing the output as filename

In one of my Bash scripts, there's a point where I have a variable SCRIPT which contains the /path/to/an/exe, and what the script ultimately needs to do, is executing that executable. Therefore the last line of the script is
$($SCRIPT)
so that $SCRIPT is expanded to /path/to/an/exe, and $(/path/to/an/exe) executes the executable.
However, running shellcheck on the script generates this error:
In setscreens.sh line 7:
$($SCRIPT)
^--------^ SC2091: Remove surrounding $() to avoid executing output.
For more information:
https://www.shellcheck.net/wiki/SC2091 -- Remove surrounding $() to avoid e...
Is there a way I can rewrite that $($SCRIPT) in a more appropriate way? eval does not seem to be of much help here.
$($SCRIPT) indeed does not do what you think it does.
The outer $() will execute any commands inside the parenthesis and execute the result string.
The inner $SCRIPT will expand to the value of the SCRIPT variable and execute this string while splitting words on spaces/
If you want to execute the command contained into the SCRIPT variable, you just write as an example:
SCRIPT='/bin/ls'
"$SCRIPT" # Will execute /bin/ls
Now if you also need to handle arguments with your SCRIPT variable command call:
SCRIPT='/bin/ls'
"$SCRIPT" -l # Will execute /bin/ls -l
To also store or build arguments dynamically, you'd need an array instead of a string variable.
Example:
SCRIPT=(/bin/ls -l)
"${SCRIPT[#]}" # Will execute /bin/ls -l
SCRIPT+=(/etc) # Add /etc to the array
"${SCRIPT[#]}" # Will execute /bin/ls -l /etc
It worked for me with sh -c:
$ chrome="/opt/google/chrome/chrome"
$ sh -c "$chrome"
Opening in existing browser session.
It also passed the ShellCheck without any issues.
with bash, just use $SCRIPT:
cat <<'EOF' > test.sh
SCRIPT='echo aze rty'
$SCRIPT
EOF
bash test.sh
produce:
aze rty

Replance extension for shell script error

I am trying to write shell script (sh), Where I am getting below error
variable i contains:
test.txt
code:
echo "${i/.txt/}"
Error:
just.sh: 16: just.sh: Bad substitution
expected output string :
text
Reproduce steps
Create file:
touch text.txt
Create file test.sh contents using any of editor
code:
#!/bin/sh
for i in `find *.txt`
do
echo "$i"
echo "${i/.txt/}"
done
How to run:
sh test.sh
sh is not bash. Fix your shebang (the 1st line) as #!/bin/bash first.
References
Difference between sh and bash, search "expansion" in the thread
Bash features a rich set of expanded non-standard parameter expansions such as ${substring:1:2}, ${variable/pattern/replacement}, case conversion, etc.

Makefile - Syntax error with for-loop

In a Makefile, I need to cycle through a list and write the current element of the list in a file.
The code is the following:
SHELL := /bin/bash
LIST = A B C
test:
for i in $(LIST) do \
echo $ii > file.txt \
done
I get the following error:
/bin/bash: -c: line 1: syntax error near unexpected token `>'
Do you know how to fix it?
You are missing a ; after $(LIST). You need to terminate the list of words you are giving to for before you can start the do block.
As indicated in the comments, you additionally need a : at the end of the echo line (the command that gets run has no newlines the way this works at the normal command line so you need to explicitly separate the commands from each other).
And further, to get the results you expect, you need to escape the $ in the shell command by using $$i (also pick one of $i or $ii as your variable name).

Shell script - check the syntax

How to check the correctness of the syntax contained in the ksh shell script without executing it? To make my point clear: in perl we can execute the command:
perl -c test_script.pl
to check the syntax. Is something similar to this available in ksh?
ksh -n
Most of the Borne Shell family accepts -n. tcsh as well.
I did a small test with the following code:
#!/bin/bash
if [ -f "buggyScript.sh" ; then
echo "found this buggy script"
fi
Note the missing ] in the if. Now I entered
bash -n buggyScript.sh
and the missing ] was not detected.
The second test script looked like this:
#!/bin/bash
if [ -f "buggyScript.sh" ]; then
echo "found this buggy script"
Note the missing fi at at end of the if. Testing this with
bash -n buggyScript.sh
returned
buggyScript.sh: line 5: syntax error: unexpected end of file
Conclusion:
Testing the script with the n option detects some errors, but by no means all of them. So I guess you really find all error only while executing the script.
The tests that you say failed to detect syntax errors, where not in fact syntax errors...
echo is a command (OK a builtin, but still a command) so ksh/bash are not going to check the spelling/syntax of your command.
Similarly "[" is effectively an alias for the test command, and the command expects the closing brace "]" as part of its syntax, not ksh/bash's.
So -n does what it says on the tin, you just haven't read the tin correctly! :-)

Problem with temporary unnamed pipe in bash script

I have the following question:
When I execute the following script directly in a terminal window, the commands behave as expected.
$ diff <(echo tmp) <(echo tmp1)
1c1
< tmp
---
> tmp1
However when I write the same command in a shell script
#! /bin/bash
diff <(echo tmp) <(echo tmp1)
I get the following error message:
$ sh test.sh
test.sh: line 2: syntax error near unexpected token `('
test.sh: line 2: ` diff <(echo tmp) <(echo tmp1)'
Initially I thought this was an issue with diff, but this also happens with other commands. Does anybody have an idea what causes the problem?
Try
bash test.sh
or
chmod ugo+x test.sh
./test.sh
Works fine for me when I do either.
Looks like the syntax is not supported by the bourne shell (sh).
When bash is invoked using sh, it starts up in a special, POSIX-compliant mode. This has different syntax, which I guess explains the different results.
See bashref of POSIX mode, #22: "process substitution is not available".
That syntax doesn't look familiar. Are you sure you are using bash in your terminal? You can verify by typing echo $SHELL.

Resources