Powershell implementation to pipe array into command - powershell

I'm using the following Powershell command to copy one user's Mercurial.ini file into another user's profile:
> copy $env:USERPROFILE\..\benm\Mercurial.ini $env:USERPROFILE\..\alex\Mercurial.ini
That works well. However, I'd like to write it in such as way so that I can do something like the following, specifying the users up front and piping them in to the copy command:
> "benm","alex" | copy "$env:UserProfile\..\$_[0]\Mercurial.ini" "$env:UserProfile\..\$_[1]\Mercurial.ini"
However, the above doesn't work. Is there an elegant way to achieve what I'm trying to do?

Something like this?
,("benm","alex") |
foreach {copy "$env:UserProfile\..\$($_[0])\Mercurial.ini" "$env:UserProfile\..\$($_[1])\Mercurial.ini"}
The ,("benm","alex") syntax makes the input from the pipeline a 2D array
PS C:\> $x = ,("benm","alex")
PS C:\> $x[0]
benm
alex
PS C:\> $x[0][0]
benm
PS C:\> $x[0][1]
alex
The Powershell pipeline will automatically "unroll" arrays and collections into a stream of objects, but only one level deep for nested arrays. By making it a 2D array, it "unrolls" the first level, and passes the nested array through the pipelile intact.

Related

Format command output in powershell

I have a output like below from a command
IpPrefix
--------
15.181.232.0/21
142.4.160.136/29
3.2.0.0/24
161.188.154.0/23
Using above output, need write a command in powershell to get format like :
15.181.232.0/21,142.4.160.136/29,3.2.0.0/24,161.188.154.0/23
Basically combine multiple lines to one line with comma separated. Please help.
Welcome to PowerShell! The results of commands are objects. This object you have made has at least 1 property called IpPrefix. If your object is stored in a variable $object, then you can reference the property like this:
$object = (some-command -param something)
$object.IpPrefix
Once you're got the items in just that one column, without the column header, you now have an array of strings. They're still objects, but they are string objects.
The -join operator works against arrays.
$object = (some-command -param something)
$object.IpPrefix -join ','
This will give you what you want in the simplest way possible.
Let's say maybe you don't want to store your data in a variable (aka in Memory). You might have a pipeline or some other situation where storing the data slows you down. You would do that like this:
(some-command -param something).IpPrefix -join ','
Same idea, different syntax. Hope this helps you understand the shell better!

Can I Pipe Powershell output to an accelerator?

I've obtained a file path to an xml-resource, by interrogating task scheduler arguments.
I'd like to pipe these files paths to [xml], to return data using XPath.
Online I see accelerators and variables are used, eg
$xml = [XML](Get-Content .\Test.xml)
tried piping to convert-to-xml, but that's an XML object containing the filepath, so I need to convert to [xml] - hoping to do this in the pipeline, potentially for > 1 xmldocument
Is it possible to pipe to [typeaccelerators] ?
Should I be piping to New-Object, or Tee-Variable, as required?
I hope to eventually be able to construct a one-liner to interrogate several nodes (eg LastRan, LastResult)
currently I have this, which only works for one
([xml](Get-Content ((Get-ScheduledTask -TaskPath *mytask* | select -First 1).Actions.Arguments | % {$_.Split('"')[-2]}))).MyDocument.LastRan
returns the value of LastRan, from MyDocument node.
Thanks in advance 👍
If you want to take pipeline input you need to make a function and set the parameter attribute ValueFromPipeline
Function Convert-XML {
Param(
[Parameter(ValueFromPipeline)]$xml
)
process{
[xml]$xml
}
}
Then you could take the content of an xml file (all at once, not line by line)
Get-Content .\Test.xml -Raw | Convert-XML
Of course to get your one liner you'd probably want to add the logic for that in the function. However this is how you'd handle pipeline input.

powershell confused about array loop, foreach method, string?

I'm trying to export all CA certificates to a directory in Base64 format, I'm new to powershell, since I'm used to doing scripts with bash. Somehow I'm not seeing something that feels like it should be obvious.
This is my line so far,
#(Get-ChildItem -path Cert:\Localmachine\ca).ForEach({Export-Certificate -Type CERT -FilePath "C:\ssl\certs.d\$_.Thumbprint" -Cert "Cert:\LocalMachine\ca\$_.Thumbprint"})
I appreciate any help, as I'm trying to learn how to be idiomatic in PS4.
This line of code contains 3 issues:
First. String interpolation with object property. PS parser doesn't understand "$var.Property", it only understands $expression within "string". But since it's expression, and not just variable name, you can make PS evaluate your line with "$(something to evaluate)". In other words, your -FilePath should be:
-FilePath "C:\ssl\certs.d\$($_.Thumbprint)"
Second. Working with objects. PS underneath is full-blown .Net Framework. Even though many objects are represented in output in a simple, predefined way, actually they are |ed to output as complete live objects. According to MSDN, the -Cert parameter is a <Certificate>, not a string pointing to a certificate, so your -Cert should be simply
-Cert $_
Third. Arrays. Get-ChildItem underneath is nothing more than DirectoryInfo.GetFileSystemInfos() which returns an array of objects. So ideally, you don't need to wrap it with anything and it's possible to simply pipe it further (Get-ChildItem | Foreach-Object{...}). But many people have different tastes on PS syntax, so the form of (gci).ForEach({...}) (without #) has the right to live as well. But what you are doing in form of #(...) is creating a new array of one item being the array returned to you by gci. So technically, it just shouldn't work. It will though, because PS saves you from such mistakes automatically: in PS you can work with array of 1 item in the same way as with this item directly (unless explicitly specified opposite). To illustrate,
#(4).Length # returns 1
#(#(2,3)).Length # returns 2
#(,#(2,3)).Length #returns 1
Thus, your current syntax for Get-ChildItem is error-prone and relies on automatic PS error-handling sugar. I recommend to either remove # in the beginning, or to rewrite in form of
Get-ChildItem -...... | Foreach-Object {...}

What does the vertical line character mean in powershell?

I am using a script from here
http://blog.kuppens-switsers.net/sharepoint/finding-cewps-with-script-in-your-sharepoint-sites/
And there is a specific part of the script that I don't understand. In this part
# Libraries and lists have views and forms which can contain webparts... let's get them also
$lists = $web.GetListsOfType("DocumentLibrary") | ? {$_.IsCatalog -eq $false}
What exactly does | ? {$_.IsCatalog -eq $false} mean? And if possible does anyone know why this person chose to only check document libraries?
What the point of the script is, it scans all content editor web parts and checks if their contents have any script tags.
Thanks
PowerShell heavily relies on the concept of the pipeline. You execute a command which returns a collection of objects and you pipe those into another command which does something with it.
| also known as the pipe character or pipe operator is used to connect the various parts of the pipeline.
In your case, you get all DocumentLibraries in a SharePoint website and pipe (pass) them into a Where-Object cmdlet (? for short) to apply a filter. The result is then assign to a variable.

Colorize findstr/grep output in PowerShell

I've found quite a few questions/answers and other types of posts that talk about using alias to substitute, or alias, grep for findstr. While this is useful, one of things I like about grep in many terminal environments is that the found text is highlighted; often in red.
findstr /A:color seems to imply that this should be possible and even easy...but I've yet to make it work in a simple statement like:
set-alias grep "findstr /A:color F0"
Is there way to do this?
Thanks
I seldomely create new aliases, so there might very well be other (better) ways than the one I write above below, but this way seems to work.
The help section on Set-Alias, for the parameter Value states:
-Value
Specifies the name of the cmdlet or command element that is being aliased.
So it expects the aliased command to either be a cmdlet or a command element.
If you do Get-Help Set-Alias -Examples you'll see the last example which does something similar to what you are hoping for, to call a command and specify some hard coded parameters. It does this with the following code:
PS C:\>function CD32 {set-location c:\windows\system32}
PS C:\>set-alias go cd32
So what you need to do is to create a function which does what you want and then alias that command. An example of this would be:
function Search-Text
{
& c:\Windows\system32\findstr.exe /A:F0 $Args
}
Then you could alias that new function to grep like:
Set-Alias grep Search-Text
And finally just call it like:
grep mysearchword file1.txt file2.txt
Note: The above code works fine for me when I run it in the ordinary PowerShell shell (probably since this is actually the ordinary command shell with some extra stuff), but does not get the expected colored printing in the ISE (obviously the ISE handles the host printing differently).