i have following situation:
a powershell script with this variables:
$RUBY = "C:\installing\ruby\bin\ruby.exe"
$ARGS = "C:\files\sript.rb $Arg1 $Arg2 $Arg3"
in a batch file i can write
%RUBY% %ARGS%
and it works.
but how can i do this in powershell?
It is important that the ruby installing path is variable.
I tried it with Start-Process but only ruby.exe was started, without script.
Any hints?
Thanks.
First, $args is an automatic variable managed by PowerShell, so I would avoid trying to declare your own variable with the same name.
To invoke a command stored in a variable from PowerShell, you can use the call operator &:
& $ruby 'script.rb'
If you need to build up the list of arguments, I would recommend creating an array, instead of mashing them all together into a single string:
$rubyArgs = #('C:\files\script.rb', $Arg1, $Arg2, $Arg3)
& $ruby $rubyArgs
If you need to pass more complicated arguments, you may find this answer useful.
Related
I don't know much about powershell, but I would like to run another script from powershell, and also pass along all the unused arguments. In bash I am doing it this way (simplified):
MY_PARAM=$1
shift
python otherscript.py "$#"
I have tried many things in powershell but nothing worked. In my python script I either received "System.Object[]" (or "System.Collections.Generic.List`1[System.Object]") or all the arguments wrapped in a single string as the first argument (or various error messages of course). I have tried:
python otherscript.py $args
Invoke-Expression "python otherscript.py $args"
And in place of $args I have also tried using $MyInvocation.Line or $MyInvocation.UnboundArguments
What is the proper syntax for this?
Update 1
As Mathias R. Jessen comments, invoking the python script from the "global scope" with python otherscript.py $args works as I would expect.
What I am actually trying to do, is call my python script from within a function:
param (
[string]$command = ""
)
function Invoke-Other() {
python otherscript.py $args
}
switch ($command) {
"foo" {
Invoke-Other $args
}
}
This is the setup, when I get a single, "wrapped" argument "bar baz", when I call my powershell script with .\myscript.ps1 foo bar baz.
When you call Invoke-Other $args the argument list is passed as a single (array) argument, so all script arguments end up as a nested array in $args[0] inside the function. You can verify that by checking the value of $args.Count inside and outside the function. The nested array then gets mangled into a string when you call the Python script with the argument list of the function.
Use splatting to have the argument list of the script passed as individual arguments to the function:
Invoke-Other #args
Ordinarily I would invoke Perl and supply required arguments from within a bash script simply using:
perl script.pl arg1
However there are cases when I want to store both the perl script directory and the arguments in bash variables:
PERLDIR = "/example/directory/script.pl"
ARG1 = "40"
When trying to call the perl script using:
perl "$PERLDIR"
It works, however when trying to provide the argument i'm not sure of the syntax to utilise. If I use:
perl "$PERLDIR $ARG1" it'll attempt to open the directory:
/example/directory/script.pl 40
And throw an error.
Is there a way to do this and if so, how?
You should use:
perl "$PERLDIR" "$ARG1"
When you use many variables in one string enclosed with " it becomes one argument.
I have installed cygwin and I am about to execute a script written in powershell. I do it like this:
powershell "& ""C:\my\script.ps1"""
This works as expected, I have to do this that way because in that script I am executing another external command and so on ...
I would like to add some environment variable to that script, so I would like to write something like
powershell "$FOO="bar"; & ""C:\my\script.ps1"""
so I can then access $FOO variable in the script and do something with it. The idea is that if that variable is not defined, I use some default value. I know that this could be also achieved with some environment variables or I could put these variables to the profile (profile.ps1) but I want to get rid of that file so I need none and I can override the default value with the variables as I showed.
but is says that:
=bar : The term '=bar' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:1
So I was thinking that something like this could work:
powershell { $web = "google.com" ; & ping.exe $web }
But it works only in powershell console and not in cygwin, it cygwin it says that
-bash: syntax error near unexpected token `&'
So it seems like that & is treaten as bash character. I tried to escape it in thousand ways, e.g.
bash -c "'powershell { \$web = \"google.com\" ; & ping.exe \$web }'"
But this is the output
bash: powershell { $web = "google.com" ; & ping.exe $web }: command not found
Thank you for a hint.
UPDATE
I am able to do this:
powershell "Invoke-Command -ScriptBlock {\$env:FOO = \"google.com\" ; & ""C:\my\script.ps1"" }"
But when I am trying to access that FOO variable throught $env:FOO it is empty, it seems like I am unable to do so because that script is running in another scope or what ...
this command will pass an environment variable from cygwin ($FOO="bar") to powershell, then run another powershell command (dir env:) which lists the environment variables (proving that it was set):
powershell "\$env:FOO=\"bar\";dir env:"
replace the dir env: part with your script call and this should work for you.
edit: here's the command (quoted slightly differently) including the call to an external script:
powershell '$env:FOO="bar";& "C:\script name.ps1"'
I'm trying to access the original command line argument string in Ruby (ie - not using the pre-split/separated ARGV array). Does anyone know how to do this? For example:
$> ruby test.rb command "line" arguments
I want to be able to tell if 'line' had quotes around it:
"command \"line\" arguments"
Any tips? Thanks in advance
As far as I can tell, ruby is not removing those double-quotes from your command line. The shell is using them to interpolate the contents as a string and pass them along to ruby.
You can get everything that ruby receives like this:
cmd_line = "#{$0} #{ARGV.join( ' ' )}"
Why do you need to know what is in quotes? Can you use some other delimiter (like ':' or '#')?
If you need to, you can pass double-quotes to ruby by escaping them:
$> ruby test.rb command "\"line\"" arguments
The above cmd_line variable would receive the following string in that case:
test.rb comand "line" arguments
I think it's unlikely, as far as I know that's all dealt with by the shell before it gets passed to the program.
On Unix systems, the command line shell (Bash, csh, etc.) automatically converts such syntax into argument strings and sends them to the Ruby executable. For instance, * automatically expands to each file in a directory. I doubt there is a way to detect this, and I ask why you want to do so.
This should help:
cmdline = ARGV.map{|x| x.index(/\s/) ? "\"#{x}\"":x}.join " "
Since shell groups the words inside quotes into one argument, we need to check if each argument has whitespace in it, and if it does, put quotes around it.
It still won't preserve wildcards (*), env variables ($VAR), and other stuff that shell expands before passing it to your script.
To be able to pass a command as it is, without expansions, you'd have to resort to passing it in through IO, like echo "ls *" | my_script.rb
Ruby has a special module for this purpose.
http://ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html
What you want is just:
require 'shellwords'
Shellwords.join ARGV[1..-1]
:p
i have unix shell script which is need to be run like below
test_sh XYZ=KLMN
the content of the script is
#!/bin/ksh
echo $XYZ
for using the value of XYZ i have do set -k before i run the script.
is there a way where i can do this without doint set -k before running the script. or is there something that i can do in the script where i can use value of the parameter given while running the script in the below way
test_sh XYZ=KLMN
i am using ksh.
Any help is appreciated.
How about running this?
XYZ=KLMN ./test_sh //running from directory where test_sh is
If your script needs no other arguments, a quick and dirty way do to it is to put
eval "$#"
at the start of your script. This will evaluate the command line arguments as shell commands. If those commands are to assign a shell/environment variable, then that's what it will do.
It's quick-and-dirty since anything could be put on the command line, causing problems from a syntax error to a bad security hole (if the script is trusted).
I'm not sure if "$#" means the same in ksh as it does in bash - using just $* (without quotes) would work too, but is even dirtier.
It looks like you are trying to use the environment variable "INSTANCE" in your script.
For that, the environment variable must be set in advance of executing your script. Using the "set" command sets exportable environment variables. Incidentally, my version of ksh dates from 1993 and the "-k" option was obsolete back then.
To set an environment variable so that it is exported into spawned shells, simply use the "export" command like so:
export INSTANCE='whatever you want to put here'
If you want to use a positional parameter for your script -- that is have the "KLMN" value accessed within your script, and assuming it is the first parameter, then you do the following in your script:
#!/bin/ksh
echo $1
You can also assign the positional parameter to a local variable for later use in your script like so:
#!/bin/ksh
param_one=$1
echo $param_one
You can call this with:
test_sh KLMN
Note that the spacing in the assignment is important -- do not use spaces.
I am tring this option
#!/bin/ksh
echo $1
awk '{FS="=";print $2}' $1
and on the command line
test_sh INSTANCE=LSN_MUM
but awk is failing.is there any problem over here?
Probably #!/bin/ksh -k will work (untested).