I have a bash script like this with a function
_launch()
{
${1}
}
testx()
{
_launch "TESTX=1 ls -la"
}
testx
I get error "TESTX=1 command not found" in _launch function. Why?
When I run TESTX=1 ls -la directly on shell it works fine.
It's not a good idea to use variables to hold commands. See BashFAQ/050
As long as you are dealing with executables and not shell built-ins, you could do this:
_launch() {
env $1
}
This won't play well in case you have literal spaces in values used in var=value pairs or arguments to the command being launched.
You can overcome this problem by just passing the command to the launch function and setting your variables in function invocation itself, like this:
_launch() {
# your launch prep steps here...
"$#" # run the command
# post launch code here
}
TESTX=1 TESTY=2 TESTZ=3 _launch ls -la
The variables would be passed down to the launched command as environment variables.
You get the error because first looks at the statement to see whether we have a variable assignment, and then does parameter expansion. In your case, bash doesn't recognize that you want to extend the environment for your ls command, and treats TESTX=1 as command to be executed.
For the same reason, the following does not set the bash variable ABC:
x='ABC=55'
$x
This would print ABC=55: command not found.
Related
In BASH, I use "pushd . " command to save the current directory on the stack.
After issuing this command in couple of different directories, I have multiple directories saved on the stack which I am able to see by issuing command "dirs".
For example, the output of "dirs" command in my current bash session is given below -
0 ~/eclipse/src
1 ~/eclipse
2 ~/parboil/src
Now, to switch to 0th directory, I issue a command "cd ~0".
I want to create a bash alias command or a function for this command.
Something like "xya 0", which will switch to 0th directory on stack.
I wrote following function to achieve this -
xya(){
cd ~$1
}
Where "$1" in above function, is the first argument passed to the function "xya".
But, I am getting the following error -
-bash: cd: ~1: No such file or directory
Can you please tell what is going wrong here ?
Generally, bash parsing happens in the following order:
brace expansion
tilde expansion
parameter, variable, arithmetic expansion; command substitution (same phase, left-to-right)
word splitting
pathname expansion
Thus, by the time your parameter is expanded, tilde expansion is already finished and will not take place again, without doing something explicit like use of eval.
If you know the risks and are willing to accept them, use eval to force parsing to restart at the beginning after the expansion of $1 is complete. The below tries to mitigate the damage should something that isn't eval-safe is passed as an argument:
xya() {
local cmd
printf -v cmd 'cd ~%q' "$1"
eval "$cmd"
}
...or, less cautiously (which is to say that the below trusts your arguments to be eval-safe):
xya() {
eval "cd ~$1"
}
You can let dirs print the absolute path for you:
xya(){
cd "$(dirs -${1-0} -l)"
}
I have a bash script that when ran, produces output like this:
VAR1=test
VAR2=test
I want to pass these variables as environment variables to an npm script, which in this case is just running mocha in the current directory, like if I was running VAR1=test VAR2=test mocha.
Thanks in advance.
It's not a great design for a bash script to output shell variable assignments like that, but you can work around it with a wrapper script runwithvars:
#!/bin/bash
set -a # Auto-export all new variables
eval "$(mybashscript)" # Perform whichever actions the script outputs
exec "$#" # Execute the specified command
Now you can use runwithvars mocha to run mocha with those variables.
Note that if the script outputs key-value pairs instead of shell variable assignments, e.g. VAR1=some value with spaces instead of VAR1='some value with spaces', then this answer does not apply and could be fragile or dangerous.
Use export:
export VAR1=test
export VAR2=test
If I run a custom bash function under shell console:
~/w/dotfiles/ruby [g:master-] ΒΆ repository_root
/Users/tian/Documents/workspace/dotfiles
And if I run the custom bash function under IRB:
irb(main):001:0> `repository_root`
(irb):1: command not found: repository_root
=> ""
How could I get the same result in IRB?
# declare
repository_root () {
if git_is_repository ; then
git_show_repository_root
fi
}
Assuming your function is in one of your bash profile files, you want to start up an interactive (-i) login (-l) shell to execute (-c) your function:
output = %x{bash -lic 'repository_root'}
One way to do this is to make a command out of the function.
Here's a short how-to
Create a shell script file that calls the function.
Create a .bin directory in your HOME and add it to $PATH in .bash_rc.
Place the shell script file in .bin.
source .bash_rc to update the $PATH variable you just changed.
Assuming you named the file fnx, just use the back tick operator or exec to run
the command - exec("fnx")
where is repository_root declared?
.bash_profile? .bashrc?
try to source that file before using repository_root
`. /path/to/file/declaring/repository_root; repository_root`
I am trying to make a new command which runs a shell script that takes in arguments.
So, I have the command in my .bash_profile:
command() {
/Users/myname/filepath/MyScript.sh
}
but MyScript.sh can take in arguments. So how can I modify this code to handle arguments so that it will pass those arguments to MyScript.h?
I think you're looking for a bash alias:
alias mycommand="/Users/myname/filepath/MyScript.sh $#"
Assuming you want all parameters to command to go to MyScript.sh, then try this:
command() {
/Users/myname/filepath/MyScript.sh "$#"
}
I am trying to get Bash to execute the following minimized example properly:
# Runs a command, possibly quoted (i.e. single argument)
function run()
{
$*
}
run ls # works fine
run "ls" # also works
run "ls `pwd`" # also works, but pwd is eagerly evaluated (I want it to evaluate inside run)
run "ls \\\`pwd\\\`" # doesn't work (tried other variants as well)
To summarize, I am trying to get the ability of having commands in quoted strings (or not), and not having any of the command, including nested shell commands through backticks, calculated values, etc., evaluated before run() is called. Is this possible? How can I achieve this?
Well the way to do this sort of thing is to use the eval function associated with an escaped '$' :
function run()
{
eval $*
}
my_command="ls \$(pwd)"
Escaping '$' as '\$' ensure that my_command will be set to "ls $(pwd)" with no substitution. Then eval will provide the substitution ^^
then
run $my_command
cd ..
run $my_command
prove that you get your functionnality !
my2c