I recently learned that you can use special characters in PowerShell variables, e.g.: ${hello world!}, but then I stumbled across this:
${^}
What does it do? I first thought it referenced the newest created variable, but it does other stuff I haven't really figured out.
The documentation says:
Contains the first token in the last line received by the session.
Examples:
dir c:\windows 🡒 dir
0..9 🡒 0
&{ dir } 🡒 &
It was likely introduced to get the last command used (dir, copy, rm, ...), but in reality that will only work for the most simplest cases, and thus it's not very useful.
The corresponding $$ returns the last token from the last line.
Note: The curly braces {} are only necessary for variable names containing characters which are not allowed in variables, except automatic variables (look here). In this case, you can omit them:
$^
It shows the first word/token in the last executed command.
Related
I have been asked to review and edit, if needed, some scripts. I have entered the relevant part of this one below. I believe its correct, but I cannot figure out if the period at the beginning of the second to last line is needed or just a typo. It appears to be a source operator, but I don't see why it'd be needed there.
As always, you folks here are the salt of the earth and deserve much more plaudits than you get and than I can give. Thank you so much for continuing to making me look better at this than I am.
$Assembly = 'D:\MgaLin2.dll'
."C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" -codebase -tlb $Assembly
Copy-Item -Path D:\Mga -Destination "C:\Program Files (x86)\Common Files\COMPANY_NAME\COMPANY_SUBFOLDER\" -Include *.*
The use of a period (.) (the dot-sourcing operator) is unusual in this case, but it works.
More typically, you'll see use of &, the call operator in this situation.
Only for PowerShell scripts (and script blocks, { ... }) does the distinction between . and & matter (. then dot-sources the code, i.e. runs it directly in the caller's scope rather than in a child scope, as & does).
For external programs, such as RegAsm.exe, you can technically use . and & interchangeably, but to avoid conceptual confusion, it is best to stick with &.
Note that the reason that & (or .) is required in this case is that the executable path is quoted; the same would apply if the path contained a variable reference (e.g., $env:ProgramFiles) or a subexpression (e.g., $($name + $ext)).
For more information about this requirement, which is a purely syntactic one, see this answer.
I have a TCL script that is run by Libero using a file path provided as an argument to open a project. The file path is C:\Users\me\Documents\FPGA projects\file.prjx
I am running the script according to Libero TCL Reference Guide (pages 51 - 52) to run the script on the command line. On page 47, the doc outlines how to work with filenames with spaces; using braces or in the case where it is used as an argument use double quotes.
The command I am trying to execute is:
Path\to\libero SCRIPT:export.tcl SCRIPT_ARGS:""C:\Users\me\Documents\FPGA projects\file.prjx""
The outer set of double quotes is to follow the syntax outlined in page 52 of the document for providing arguments and the inner set of double quotes is to handle the white space in the first argument. I had expected $argv 0 to be C:\Users\me\Documents\FPGA projects\file.prjx, but instead $argv 0 is actually C:\Users\me\Documents\FPGA.
I added a print statement to the script to print $argv:
puts $argv
This gives a result of C:\Users\me\Documents\FPGA so the rest of the file path is not being interpreted as even being a second argument.
My assumption is that the conventions outlined in the document are just standard TCL conventions for providing a file path containing forward slashes and spaces as an argument. I have not been able to find an example of passing a similarly formatted argument in TCL. Any ideas?
I'm not sure it's the same issue but, having MagicSplat tclsh.exe and wish.exe linked to *.tcl and *.tk files in Windows (7 to 11), calling scripts this way:
processDIR.tcl "c:\My directory\subdir"
evals arguments only till first space, becoming "c:\My" BUT calling scripts like this:
tclsh.exe processDIR.tcl "c:\My directory\subdir"
trespasses complete argument.
Could you give it a try?
I am currently working on a project but I have one big problem. I have some picture with a whitespace in the name and I want to do a montage. The problem is that I can't rename my picture and my code is like that :
$pic1 = qq(picture one.png);
$pic2 = qq(picture two.png);
my $cmd = "C:\...\montage.exe $pic1 $pic2 output.png";
system($cmd);
but because of the whitespace montage.exe doesn't work. How can I execute my code without renaming all my pictures?
Thanks a lot for your answer!
You can properly quote the filenames within the string you pass to system, as #Borodin shows in his answer. Something like: system("montage.exe '$pic1' '$pic2'")
However, A more reliable and safer solution is to pass the arguments to montage.exe as extra parameters in the system call:
system('montage.exe', $pic2, $pic2, 'output.png')
Now you don't have to worry about nesting the correct quotes, or worry about files with unexpected characters. Not only is this simpler code, but it avoids malicious injection issues, should those file names ever come from a tainted source. Someone could enter | rm *, but your system call will not remove all your files for you.
Further, in real life, you probably are not going to have a separate scalar variable for each file name. You'll have them in an array. This makes your system call even easier:
system('montage.exe', #filenames, 'output.png')
Not only is that super easy, but it avoids the pitfall of having a command line too long. If your filenames have nice long paths (maybe 50-100 characters), a Windows command line will exceed the max command length after around 100 files. Passing the arguments through system() instead of in one big string avoids that limitation.
Alternatively, you can pass the arguments to montage.exe as a list (instead of concatenating them all into a string):
use strict;
use warnings;
my $pic1 = qq(picture one.png);
my $pic2 = qq(picture two.png);
my #cmd = ("C:\...\montage.exe", $pic1, $pic2, "output.png");
system(#cmd);
You need to put quotes around the file names that have spaces. You also need to escape the backslashes
my $cmd = qq{C:\\...\\montage.exe "$pic1" "$pic2" output.png};
In unix systems, the best approach is the multi-argument form of system because 1) it avoids invoking a shell, and 2) that's the format accepted by the OS call. Neither of those are true in Windows. The OS call to spawn a program expects a command line, and system's attempt to form this command line is sometimes incorrect. The safest approach is to use Win32::ShellQuote.
use Win32::ShellQuote qw( quote_system );
system quote_system("C:\\...\\montage.exe", $pic1, $pic2, "output.png");
This is a weird one. Normally when I execute an external command from powershell I use the & operator like this:
& somecommand.exe -p somearguments
However, today I came across the . operator used like this:
.$env:systemdrive\chocolatey\chocolateyinstall\chocolatey.cmd install notepadplusplus
What purpose does the period serve in this scenario? I don't get it.
The "." dot sourcing operator will send AND receive variables from other scripts you have called. The "&" call operator will ONLY send variables.
For instance, considering the following:
Script 1 (call-operator.ps1):
clear
$funny = "laughing"
$scriptpath = split-path -parent $MyInvocation.MyCommand.Definition
$filename = "laughing.ps1"
"Example 1:" # Call another script. Variables are passed only forward.
& $scriptpath\$filename
"Example 2:" # Call another script. Variables are passed backwards and forwards.
. $scriptpath\$filename
$variableDefinedInOtherScript
Script 2 (laughing.ps1):
# This is to test the passing of variables from call-operator.ps1
"I am $funny so hard. Passing variables is so hilarious."
$variableDefinedInOtherScript = "Hello World!"
Create both scripts and ONLY run the first one. You'll see that the "." dot sourcing operator sends and receives variables.
Both have their uses, so be creative. For instance, the "&" call operator would be useful if you wanted to modify the value(s) of variables in another script while preserving the original value(s) in the your current script. Kinda a safeguard. ;)
The Short:
It is a Special Operator used to achieve what regular operators cannot achieve. This particular operator . actually has two distinctively different Special Operator use cases.
The Long:
As with any other language, scripting or otherwise, PowerShell script also supports many different types of Operators to help manipulate values. These regular operators include:
Arithmetic
Assignment
Comparison
Logical
Redirection
List item
Split and Join
Type
Unary
However, PowerShell also supports whats known as Special Operators which are used to perform tasks that cannot be performed by the other types of operators.
These Special Operators Include:
#() Array subexpression operator
& Call operator
[ ] Cast operator
, Comma operator
. Dot sourcing operator
-f Format operator
[ ] Index operator
| Pipeline operator
. Property dereference operator
.. Range operator
:: Static member operator
$( ) Subexpression operator
. Dot sourcing operator: is used in this context to allow a script to run in the current scope essentially allowing any functions, aliases, and variables which has been created by the script to be added to the current script.
Example:
. c:\scripts.sample.ps1
NoteThat this application of the . Special Operator is followed by a space to distinguish it from the (.) symbol that represents the current directory
Example:
. .\sample.ps1
. Property dereference operator: Allows access to the properties and methods of of an object which follows the . by indicating that the expression on the left side of the . character is an object and the expression on the right side of the is an object member (a property or method).
Example:
$myProcess.peakWorkingSet
(get-process PowerShell).kill()
Disclaimer & Sources:
I had the same question while looking at a PowerShell script that I was trying to expand on its feature sets and landed here when doing my research for the answer. However I managed to find my answer using this magnificent write up on the Microsoft Development Network supplemented with this further expansion of the same ideas from IT Pro.
Cheers.
The dot is a call operator:
$a = "Get-ChildItem"
. $a # (executes Get-ChildItem in the current scope)
In your case, however, I don't see what it does.
.Period or .full stop for an objects properties; like
$CompSys.TotalPhysicalMemory
See here: http://www.computerperformance.co.uk/powershell/powershell_syntax.htm#Operators_
This answer is to expand slightly upon those already provided by David Brabant and his commenters. While those remarks are all true and pertinent, there is something that has been missed.
The OPs use of & when invoking external commands is unnecessary. Omitting the & would have no effect (on the example of his usage). The purpose of & is to allow the invocation of commands whose names are the values of a (string) expression. By using the & above, powershell then (essentially) treats the subsequent arguments as strings, the first of which is the command name that & duly invokes. If the & were omitted, powershell would take the first item on the line as the command to execute.
However, the . in the second example is necessary (although, as noted by others, & would work just as well in this case). Without it, the command line would begin with a variable access ($env:systemdrive) and so powershell would be expecting an expression of some form. However, immediately following the variable reference is a bare file path which is not a valid expression and will generate an error. By using the . (or &) at the beginning of the line, it is now treated as a command (because the beginning doesn't look like a valid expression) and the arguments are processed as expandable strings (" "). Thus, the command line is treated as
. "$env:systemdrive\chocolatey\chocolateyinstall\chocolatey.cmd" "install" "notepadplusplus"
The first argument has $env:systemdrive substituted into it and then . invokes the program thus named.
Note: the full description of how powershell processes command line arguments is way more complicated than that given here. This version was cut down to just the essential bits needed to answer the question. Take a look at about_Parsing for a comprehensive description. It is not complete but should cover most normal usage. There are other posts on stackoverflow and github (where powershell now resides) that cover some of the seemingly quirky behaviour not listed in the official documentation. Another useful resource is about_Operators though again this isn't quite complete. An example being the equivalence of . and & when invoking something other than a powershell script/cmdlet getting no mention at all.
Saw these variables in the debugger and I'm not sure what they do.
$_ The current pipeline object; used in script blocks, filters, the process clause of functions, where-object, foreach-object and switch
$^ contains the first token of the last line input into the shell
$$ contains the last token of last line input into the shell
$? Contains the success/fail status of the last statement
Source: http://www.computerperformance.co.uk/powershell/powershell_variables.htm#%24Dollar_variables_
Read
Get-Help About_Automatic_Variables
Its all about the goodness of automatic variables that get created when using PowerShell console.
In PowerShell, a dollar sign preceding a name indicates a variable. The symbols in question are just special cases of variables provided by the PowerShell environment. They are also known as "automatic" variables. More specifically:
$$ is a variable containing the last token of the last line input into the shell(does not contain the whole command)
$^ is a variable containing the first token of the last line input into the shell(does not contain the whole command)
$? is a variable containing the success or failure of the last statement(False if the previous command ended with an error; True otherwise.)