How to change the directory to program files using Powershell? - powershell

I would like to open a C:\Program Files\R\R-3.2.0\bin\Rscript.exe. For that I am trying to change the directory. I figured that the error is in opening Program files. Following is the code
cd Program Files\R\R-3.2.0\bin
Error: A positional parameter cannot be found that accepts argument Files

Unlike command.com/cmd.exe, PowerShell follows much more consistent rules and in the failing case Program and Files\R..bin are parsed as two separate arguments, where the second is invalid in context (as cd only accepts a single non-named argument).
To fix this use quotes, eg.
cd "C:\Program Files"
With the quotes it is parsed as a string value which is supplied as a single argument (the string itself does not include the quotes, again unlike cmd.exe rules).
FWIW, cd is an alias for Set-Location. Run get-help cd for the details on how it can be used - include which optional (and named) parameters it does support.

You need to put the path in quotes if it contains a space:
cd 'C:\Program Files\R\R-3.2.0\bin'
Either single or double quotes will work.

Related

How do I invoke a command using a variable in powershell?

I want to invoke the shutdown.exe executable in powershell and it is located on C:\WINDOWS\System32\shutdown.exe.
Since we already got the C:\WINDOWS in the variable $env:windir I want to just use it and concatenate the rest of the path into the command. I was trying this:
PS C:\Users\shina> .\$env:windir\System32\shutdown.exe -s
But I got the following error:
.\$env:windir\System32\shutdown.exe: The term '.\$env:windir\System32\shutdown.exe' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
How can I accomplish this?
You can use:
& $env:windir\System32\shutdown.exe -s
Or
. $env:windir\System32\shutdown.exe -s
(note the space).
& is the call operator. You can read more about it here:
Runs a command, script, or script block. The call operator, also known as the "invocation operator", lets you run commands that are stored in variables and represented by strings or script blocks.
. is the dot sourcing operator. You can read more about it here:
Runs a script in the current scope so that any functions, aliases, and variables that the script creates are added to the current scope, overriding existing ones.
The dot sourcing operator is followed by a space. Use the space to distinguish the dot from the dot (.) symbol that represents the current directory.

PowerShell command only works without spaces between arguments

I try certain source codes using PowerShell to extract an password protected archive using 7zip:
This command doesn' work (7zip is an alias for $7zipPath):
& 7zip x "$zipFile" -o "$output" -p $zipFilePassword
I get the this error:
Command Line Error:
Too short switch:
But when I remove the spaces between the variables -o and -p, the archive can be extracted. This behaviour confuses me with other command line tools like git etc.? Why is it so?
The behavior is specific to 7-Zip (7z.exe) and applies to whatever program (shell) you invoke it from:
Deviating from widely used conventions observed by CLIs such as git, 7z requires that even switches (options) that have mandatory arguments, such as -o and -p, have the argument directly attached to the switch name - no spaces are allowed:
& 7zip x $zipFile -o"$output" -p"$zipFilePassword"
Note that you normally need not enclose variable references in PowerShell in "..." (note how $zipFile isn't), even if they contain spaces. However, in order to attach them directly to switch names, you do.
Alternatively, you could enclose the entire token - switch name and argument - in double quotes:
& 7zip x $zipFile "-o$output" "-p$zipFilePassword"

Run command line in PowerShell

I know there are lots of posts regarding this, but nothing worked for me.
I am trying to run this command line in PowerShell:
C:/Program Files (x86)/ClamWin/bin/clamd.exe --install
I have this in PowerShell:
&"C:/Program Files (x86)/ClamWin/bin/clamd.exe --install"
But all this does is execute clamd.exe, ignoring the --install parameter
How can I get the full command line to run?
Josef Z's comment on the question provides the solution:
& "C:/Program Files (x86)/ClamWin/bin/clamd.exe" --install # double-quoted exe path
or, given that the executable path is a literal (contains no variable references or subexpressions), using a verbatim (single-quoted) string ('...'):
& 'C:/Program Files (x86)/ClamWin/bin/clamd.exe' --install # single-quoted exe path
As for why your own solution attempt failed: The call operator, &, expects only a command name/path as an argument, not a full command line.
Invoke-Expression accepts an entire command line, but that complicates things further and can be a security risk.
As for why this is the solution:
The need for quoting stands to reason: you need to tell PowerShell that C:/Program Files (x86)/ClamWin/bin/clamd.exe is a single token (path), despite containing embedded spaces.
&, the so-called call operator, is needed, because PowerShell has two fundamental parsing modes:
argument mode, which works like a traditional shell, where the first token is a command name, with subsequent tokens representing the arguments, which only require quoting if they contain shell metacharacters (chars. with special meaning to PowerShell, such as spaces to separate tokens);
that is why --install need not, but can be quoted (PowerShell will simply remove the quotes for you before passing the argument to the target executable.)
expression mode, which works like expressions in programming languages.
PowerShell decides based on a statement's first token what parsing mode to apply:
If the first token is a quoted string - which we need here due to the embedded spaces in the executable path - or a variable reference (e.g., $var ...), PowerShell parses in expression mode by default.
A quoted string or a variable reference as an expression would simply output the string / variable value.
However, given that we want to execute the executable whose path is stored in a quoted string, we need to force argument mode, which is what the & operator ensures.
Generally, it's important to understand that PowerShell performs nontrivial pre-processing of the command line before the target executable is invoked, so what the command line looks like in PowerShell code is generally not directly what the target executable sees.
If you reference a PowerShell variable on the command line and that variable contains embedded spaces, PowerShell will implicitly enclose the variable's value in double quotes before passing it on - this is discussed in this answer to the linked question.
PowerShell's metacharacters differ from that of cmd.exe and are more numerous (notably, , has special meaning in PowerShell (array constructor), but not cmd.exe - see this answer).
To simplify reuse of existing, cmd.exe-based command lines, PowerShell v3 introduced the special stop-parsing symbol, --%, which turns off PowerShell's normal parsing of the remainder of the command line and only interpolates cmd.exe-style environment-variable references (e.g., %USERNAME%).

Why does robocopy use its own command line parser?

If I execute the following command on a Windows 8.1 machine:
robocopy "C:\Temp\A\" "C:\Temp\B\"
Robocopy fails due to the following problem:
Source : C:\Temp\A" C:\Temp\B"\
Dest -
...
ERROR : No Destination Directory Specified.
It looks like \ is used as some kind of escape character (which is not normal behavior in the windows command line) The final \" is even transformed to "\ which I do not understand at all. Why's that so?
Note: this is not the default behavior of the command line, if they would have used argv[1] and argv[2] within robocopy, they would've retrieved the correct arguments.
Why are they using their own command line parsing? It really confused me for the last hour...
You should omit the trailing backslashes.
From http://ss64.com/nt/robocopy.html :
If either the source or destination are a "quoted long foldername" do
not include a trailing backslash as this will be treated as an escape
character, i.e. "C:\some path\" will fail but "C:\some path\\" or
"C:\some path." or "C:\some path" will work.
robocopy is not an exception. Any executable uses its own line parser to determine the arguments that were sent to it. The OS just uses the API to create the process and pass to it a string to be handled as arguments. The process can handle the string as it wants.
In the case of robocopy, the parser used is the standard Microsoft C startup code. This parser follow the rules described here, and in the full list you can found
A double quotation mark preceded by a backslash, \", is interpreted as
a literal double quotation mark (").

Xcopy: invalid number of parameters or file not found error

From inside a .bat file, I m issuing this command
xcopy\s Folder1\folder2\folder3\blah-blah Folder1\temp\folder2\folder3
But I get the error:
The system cannot find the path specified.
I tried copying the same line to command line and tried it:
Then, I get the error, xcopys command not found.
If I try to use xcopy instead of xcopy/s, I get error:
File not found - Folder1folder2folder3blah-blah
If I use xcopy command with backward slash on command line: Invalid number of parameters.
I tried enclosing paths in quotes, but it does not help.
My file names don't have spaces in them but they do have -
I have checked the path of source and destination and they exist
Any help will be appreciated.
Thanks
I guess you're running under windows, so you have to use forward slashes for arguments.
xcopy/s is something very different from xcopy\s. The later searches for an application called s in a subfolder called xcopy. To further avoid confusion, separate the program from its argument(s) with spaces.