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

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

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 "$#"

Run command as bash from POSIX shell

I have a quick question
I have a posix shell but I need to run a bash command.
Think
root#home:~# sh
# /bin/bash /bin/ls
However, when I do that, I get
/bin/ls: /bin/ls: cannot execute binary file
I'm sure I'm missing something simple, but I'm not sure what it is. Any help? I also need to do it in one line.
Use the -c argument to specify a command that you want to be ran by the other shell:
" -c Read commands from the command_string operand"
bash -c "ls"
I came up with a workaround
echo '#!/bin/bash\--comamnd--; chmod ugo+x /tmp/script.sh; /tmp/script.sh

How to set $TERM to a value when running /bin/bash via command line?

When I run the /bin/bash process with 2 parameters -c and SomeUserInput,
where SomeUserInput is echo $TERM
The output is
xterm-256color
Is there a way I can set the value of $TERM via a command line parameter to /bin/bash so the above invokation of echo $TERM would print something else that I specify?
(Yes, I've done a lot of digging in man bash and searching elsewhere, but couldn't find the answer; although I think it's likely there.)
First of all, since you used double quotes, that prints the value of TERM in your current shell, not the bash you invoke. To do that, use /bin/bash -c 'echo $TERM'.
To set the value of TERM, you can export TERM=linux before running that command, set it only for that shell with either TERM=linux /bin/bash -c 'echo $TERM' (shell expression), or /usr/bin/env TERM=linux /bin/bash -c 'echo $TERM' (execve compatible (as for find -exec)).
Update:
As for your edit of only using command line parameters to /bin/bash, you can do that without modifying your input like this:
/bin/bash -c 'TERM=something; eval "$1"' -- 'SomeUserInput'
Well, you can either set the variable on your .bashrc file, or simply set with the bash invocation:
/bin/bash -c "TERM=something-else; echo $TERM"

How to specify zeroeth argument

I'm writing a bash script that starts the tcsh interpreter as a login shell and has it execute my_command. The tcsh man page says that there are two ways to start a login shell. The first is to use /bin/tcsh -l with no other arguments. Not an option, because I need the shell to execute my_command. The second is to specify a dash (-) as the zeroeth argument.
Now the bash exec command with the -l option does exactly this, and in fact the following works perfectly:
#!/bin/bash
exec -l /bin/tcsh -c my_command
Except... I can't use exec because I need the script to come back and do some other things afterwards! So how can I specify - as the zeroeth argument to /bin/tcsh without using exec?
You can enclose the exec command into a sub-shell of your script.
#!/bin/bash
(exec -l /bin/tcsh -c my_command)
# ... whatever else you need to do after the command is done
You can write a wrapper (w.sh) script that contains:
#!/bin/bash
exec -l /bin/tcsh -c my_command
and execute w.sh in your main script.

Passing arguments to /bin/bash via a bash script

I am writing a bash script that takes a number of command line arguments (possibly including spaces) and passes all of them to a program (/bin/some_program) via a login shell. The login shell that is called from the bash script will depend on the user's login shell. Let's suppose the user uses /bin/bash as their login shell in this example... but it might be /bin/tcsh or anything else.
If I know how many arguments will be passed to some_program, I can put the following lines in my bash script:
#!/bin/bash
# ... (some lines where we determine that the user's login shell is bash) ...
/bin/bash --login -c "/bin/some_program \"$1\" \"$2\""
and then call the above script as follows:
my_script "this is too" cool
With the above example I can confirm that some_program receives two arguments, "this is too" and "cool".
My question is... what if I don't know how many arguments will be passed? I'd like to pass all the arguments that were sent to my_script along to some_program. The problem is I can't figure out how to do this. Here are some things that don't work:
/bin/bash --login -c "/bin/some_program $#" # --> 3 arguments: "this","is","too"
/bin/bash --login -c /bin/some_program "$#" # --> passes no arguments
Quoting the bash manual for -c:
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
Works for me:
$ cat x.sh
#!/bin/bash
/bin/bash --login -c 'echo 1:$1 2:$2 3:$3' echo "$#"
$ ./x.sh "foo bar" "baz" "argh blargh quargh"
1:foo bar 2:baz 3:argh blargh quargh
I don't know how you arrived at the "passes no arguments" conclusion, maybe you missed the $0 bit?
Avoid embedding variables into other scripts, pass them on as arguments instead. In this case:
bash --login -c 'some_program "$#"' some_program "$#"
The first argument after -c '...' is taken as $0, so I just put in some_program there.
On a side note, it's an odd requirement to require a login shell. Doesn't the user log in?

Resources