parenthesis in a directory name in bash script - bash

I get the error executing bash syntax error near unexpected token `('
I know the error is caused by the ')' but I thought placing the commands in-between ' ' is suppose to allow the parenthesis in a directory name. How can I fix this without renaming the name?
bash -c 'cd /tmp/h1/clients/04212015142432811_Fs_1000_ahh/pls/03sox_a_Fs_1000_ahh_(000_bit)_(0.0000
0sig_in_deg)_to_(508_bit)_(30.00000sig_in_deg) && exec bash xfade.sh'
please note:
It's being called from inside octave a math program like matlab

Why are you bothering with an outer shell? Quote the argument to cd:
(cd '/tmp/h1/clients/04212015142432811_Fs_1000_ahh/pls/03sox_a_Fs_1000_ahh_(000_bit)_(0.00000sig_in_deg)_to_(508_bit)_(30.00000sig_in_deg)' && exec bash xfade.sh)
If you really must use an extra bash -c...
dirname='/tmp/h1/clients/04212015142432811_Fs_1000_ahh/pls/03sox_a_Fs_1000_ahh_(000_bit)_(0.00000sig_in_deg)_to_(508_bit)_(30.00000sig_in_deg)'
bash -c 'cd "$1" && exec bash xfade.sh' _ "$dirname"

Can you use double quotes for bash -c?
bash -c "cd '/tmp/h1/clients/04212015142432811_Fs_1000_ahh/pls/03sox_a_Fs_1000_ahh_(000_bit)_(0.00000sig_in_deg)_to_(508_bit)_(30.00000sig_in_deg)' && exec bash xfade.sh"

You need to quote the path inside of the command string passed to the bash subshell. E.g.:
bash -c 'cd '"'"'/tmp/h1/clients/04212015142432811_Fs_1000_ahh/pls/03sox_a_Fs_1000_ahh_(000_bit)_(0.00000sig_in_deg)_to_(508_bit)_(30.00000sig_in_deg) && exec bash xfade.sh'"'"''
You get the error because running bash -c passes the argument string to a new shell. The argument string will have the single quotes stripped by the outer (invoking) shell.
UPDATED: to correctly quote single quotes inside single quotes as pointed out by Charles Duffy

Related

Pass all args to a command called in a new shell using bash -c

I've simplified my example to the following:
file1.sh:
#!/bin/bash
bash -c "./file2.sh $#"
file2.sh:
#!/bin/bash
echo "first $1"
echo "second $2"
I expect that if I call ./file1.sh a b to get:
first a
second b
but instead I get:
first a
second
In other words, my later arguments after the first one are not getting passed through to the command that I'm executing inside a new bash shell. I've tried many variations of removing and moving around the quotation marks in the file1.sh file, but haven't got this to work.
Why is this happening, and how do I get the behavior I want?
(UPDATE - I realize it seems pointless that I'm calling bash -c in this example, my actual file1.sh is a proxy script for a command that gets called locally to run in a docker container so it's actually docker exec -i mycontainer bash -c '')
Change file1.sh to this with different quoting:
#!/bin/bash
bash -c './file2.sh "$#"' - "$#"
- "$#" is passing hyphen to populate $0 and $# is being passed in to populate all other positional parameters in bash -c command line.
You can also make it:
bash -c './file2.sh "$#"' "$0" "$#"
However there is no real need to use bash -c here and you can just use:
./file2.sh "$#"

Proper syntax for bash exec

I am trying to do the following:
if ps aux | grep "[t]ransporter_pulldown.py" > /dev/null
then
echo "Script is already running. Skipping"
else
exec "sudo STAGE=production $DIR/transporter_pulldown.py" # this line errors
fi
$ sudo STAGE=production $DIR/transporter_pulldown.py works on the command line, but in a bash script it gives me:
./transporter_pulldown.sh: line 9:
exec: /Users/david/Desktop/Avails/scripts/STAGE=production
/Users/david/Desktop/Avails/scripts/transporter_pulldown.py:
cannot execute: No such file or directory
What would be the correct syntax here?
sudo isn't a command interpreter thus its trying to execute the first argument as a command.
Instead try this:
exec sudo bash -c "STAGE=production $DIR/transporter_pulldown.py"
This creates uses a new bash processes to interpret the variables and execute your python script. Also note that $DIR will be interpreted by the shell you're typing in rather than the shell that is being executed. To force it to be interpreted in the new bash process use single quotes.

How to pass arguments with spaces to MinGW-MSYS shell scripts from the Windows command line?

I have a sh script, myscript.sh, which takes a directory as an input argument and does some recursive processing of the files in that directory. I want to run this script in Windows command line (I use the MinGW/MSYS distribution).
How do I properly provide a path with spaces as an input argument?
For example, I want to give a path, 'dirA\dir B'. I tried many different combinations, including
sh -c 'myscript.sh "dirA/dir B"'
sh -c 'myscript.sh "dirA/dir\ B"'
sh -c "myscript.sh 'dirA/dir\\ B'"
sh -c "myscript.sh \"dirA/dir B\" "
sh -c "myscript.sh dirA/dir\ B "
But on all of them the script understands the path as 'dirA/dir'.
cmd doesn't understand single quotes. If sh does, then make the outer quotes double, so that you're double-quoting the argument at the cmd prompt, and passing the single quotes to sh to interpret.
The third option you listed is the right idea, but it's not clear to me what you're doing with the \\. Does sh require you to escape the space within a double-quoted string? If I'm not mistaken, it's either/or, not both. One of these should work (depending on whether your sh Windows port uses Unix-style forward slash path separators or Windows-style backslash separators or both):
sh -c "myscript.sh 'dirA/dir B'"
or
sh -c "myscript.sh 'dirA\dir B'"
I'm not sure why the fourth option doesn't work. That method works fine for passing double-quoted arguments to PowerShell from cmd. For example, this works:
powershell -noexit "sl \"C:\Program Files\""
This leads me to suspect that it's sh that's having a problem with the path arguments 'dirA/dir B' and "dirA/dir B" -- especially if the suggestions above don't work.
Speaking of PowerShell, you might want to give that a try instead. Any of the following should work:
sh -c 'myscript.sh "dirA/dir B"'
sh -c "myscript.sh 'dirA/dir B'"
sh -c 'myscript.sh ''dirA/dir B'''
sh -c "myscript.sh `"dirA/dir B`""

Is it possible to access the value associated with the "-c" parameter from a bash script?

I would like to do bash -c '<some smart bash script>' that would output the actual string passed to -c.
In other words, if SCRIPT is set to that smart script, bash -c "$SCRIPT" should yield what's in $SCRIPT.
Is that possible? If yes, how?
Thanks
See man bash
5.2 Bash Variables
...
BASH_EXECUTION_STRING
The command argument to the -c invocation option.
If you try
bash -c 'echo $BASH_EXECUTION_STRING'
it will give you
echo $BASH_EXECUTION_STRING

Inline bash script variables

Admittedly, I'm a bash neophyte. I always want to reach for Python for my shell scripting purposes. However, I'm trying to push myself to learn some bash. I'm curious why the following code doesn't work.
sh -c "F=\"123\"; echo $F"
It doesn't work because variable expansion in the double-quoted string happens before the command is called. That is, if I type:
echo "$HOME"
The shell transforms this into:
echo "/home/lars"
Before actually calling the echo command. Similarly, if you type:
sh -c "F=\"123\"; echo $F"
This gets transformed into:
sh -c "F=\"123\"; echo"
Before calling a the sh command. You can use single quotes to inhibit variable expansion, for example:
sh -c 'F="123"; echo $F'
You can also escape the $ with a backslash:
sh -c "F=\"123\"; echo \$F"
Not an answer to the core question, but if anyone is looking to do this inline in a (subjectively) more elegant way than bash -c:
( export MY_FLAG="Hello"; echo "$MY_FLAG" )
The syntax is nicer, no escape chars etc.

Resources