I have a requirement to request some information that comes in the form of an object. I need to replace some test in one of the properties and then write the list of objects to CSV.
When I do
Get-Process | select * | %{ $_Path.Replace("chrome", "ie") }
I have two problems
If $_.Path is null, it gives me an error that you cannot call a method on a null-valued expression
The output is a single string representing the text that was replaced (just the Path property). I need the original object and all of it's properties kept, but with the updated path value.
So of course when I try to do
Get-Process | select * | %{ $_Path.Replace("chrome", "ie") } | Export-Csv -Path "out.csv"
What I get is a single property Length because the output of the above is a string with only the Length property.
Get-Process | select * | %{ $_.Path = $_.Path.Replace("chrome", "ie"); $_ } | Export-Csv -Path "out.csv" -NoTypeInformation
$_.Path instead of $_Path
Assign the replaced text back to the path property
and output the object after doing the assignment
Help Links (if available):
Get-Process (in module Microsoft.PowerShell.Management)
select is an alias for Select-Object (in module Microsoft.PowerShell.Utility)
% is an alias for ForEach-Object
Export-Csv (in module Microsoft.PowerShell.Utility)
try this
Get-Process | select *, #{N="Path";E={$_.Path.Replace("chrome", "ie") }} -ExcludeProperty Path | export-csv -Path "c:\temp\out.csv" -NoTypeInformation
Related
I use this to get a list of folders containing .h files.
**
$type = "*.h"
$HDIRS = dir .\$type -Recurse |
Select-Object Directory -Unique |
Format-Table -HideTableHeaders
** It gives me a list of folders.
Now I want "-I " before every foldername. Common string manipulation doesn't seem to work
You still have rich objects after the select so to manipulate the strings you have to reference the one property you've selected "Directory"
$type = "*.h"
$HDIRS = Dir .\$type -Recurse |
Select-Object Directory -Unique |
ForEach-Object{
$_.Directory = "-I" + $_.Directory
$_
} |
Format-Table -HideTableHeaders
This will result in $HDIRS looking like a list of folder paths like -IC:\temp\something\something...
However, the format output objects are generally not suitable for further consumption. It looks like you're interested in the strings you could simply make this a flat array of strings like:
$type = "*.h"
$HDIRS = Dir .\$type" -Recurse |
Select-Object -ExpandProperty Directory -Unique |
ForEach-Object{ "-I" + $_ }
The mantra goes filter left, format right.
Our data:
$type = '.\*.h'
Get-ChildItem -Path $type -Recurse
The manipulation (filter):
Select-Object { "-I $($_.Directory)" } -Unique
And the format:
Format-Table -HideTableHeaders
In many cases, PowerShell cmdlets allow you to pass scriptblocks (closures) to evaluate to values and that's what I'm doing above with the Select-Object call.
I'm trying to do script for finding non-unique files.
The script should take one .csv file with data: name of files, LastWriteTime and Length. Then I try to make another .csv based on that one, which will contain only those objects whose combination of Name+Length+LastWriteTime is NON-unique.
I tried following script which uses $csvfile containing files list:
$csvdata = Import-Csv -Path $csvfile -Delimiter '|'
$csvdata |
Group-Object -Property Name, LastWriteTime, Length |
Where-Object -FilterScript { $_.Count -gt 1 } |
Select-Object -ExpandProperty Group -Unique |
Export-Csv $csvfile2 -Delimiter '|' -NoTypeInformation -Encoding Unicode
$csvfile was created by:
{
Get-ChildItem -Path $mainFolderPath -Recurse -File |
Sort-Object $sortMode |
Select-Object Name, LastWriteTime, Length, Directory |
Export-Csv $csvfile -Delimiter '|' -NoTypeInformation -Encoding Unicode
}
(Get-Content $csvfile) |
ForEach-Object { $_ -replace '"' } |
Out-File $csvfile -Encoding Unicode
But somehow in another $csvfile2 there is only the one (first) non-unique record. Does anyone have an idea how to improve it so it can list all non-unique records?
You need to use -Property * -Unique to get a list of unique objects. However, you cannot use -Property and -ExpandProperty at the same time here, because you want the latter parameter to apply to the input objects ($_) and the former parameter to apply to an already expanded property of those input objects ($_.Group).
Expand the property Group first, then select the unique objects:
... |
Select-Object -ExpandProperty Group |
Select-Object -Property * -Unique |
...
Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" | Where-Object {$_.Name -like "*transaction*"} | Select-Object -ExpandProperty FullName,LastWriteTime
I'm trying to list all files in a folder using Get-ChildItem and Select-Object property. When I try to use FullName variable to list the fully qualified file name, the file name is getting truncated. Tried to use -ExpandProperty to get fully qualified file name. It works for one field but if I try to list both FullName and LastWriteTime, it's not working.
The output from the power shell command will be used in MS SQL Server to load the file names into a specific table.
Please suggest proper syntax for my purpose. Appreciate your help!
Depending on your use case and input, one way to accomplish this is by having two Select-Object cmdlets in your pipeline, one to define an array of properties, and one to expand them:
PS C:\> $Name,$DisplayName,$Status = Get-Service
| Select-Object -First 1 -Property #{
Name = "MyProperties"
Expression = { $_.Name,$_.DisplayName,$_.DisplayName }
} | Select-Object -ExpandProperty MyProperties
Get-ChildItem -Path E:\Server_Data\main.sweetbeam.net\data\2015 -Recurse –File -include "*.txt","*.csv" | Where-Object {$_.Name -like "*transaction*"} | Select-Object #{Name="test";Expression={$_.FullName + "`t" + $_.LastWriteTime}} | Select-Object -ExpandProperty test
Merged the two fields and used the derived field for my purpose.
If you are only going to do this to display on the console, then you can look at using Format-Table with the -Wrap parameter to display all of the text on the console without truncating the output.
Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" |Where-Object {
$_.Name -like "*transaction*"
} | Format-Table FullName,LastWriteTime -Wrap
If you are planning on doing anything else with our output, then you will need to avoid the use of Format-* cmdlets as they add custom formatting to the object and render it effectively useless in the pipeline.
If you're using the output in another program, you should be converting to CSV, JSON, or XML rather than copying the formatted output. It may also be possible to insert directly into SQL using PowerShell commands.
Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" |
Where-Object {$_.Name -like "*transaction*"} |
Select-Object FullName,LastWriteTime |
ConvertTo-Csv -NoTypeInformation
Other options for the last command are:
JSON with ConvertTo-Json
XML with ConvertTo-xml -As String -NoTypeInformation
Late answer, but this has existed since PowerShell 3.0, so should have been an option.
get-eventlog Security `
-EntryType SuccessAudit `
-Newest 50 `
-InstanceId 4624,4634 `
-ComputerName $env:COMPUTERNAME |
Select-Object -Property *
OR (not all fields)
get-eventlog Security `
-EntryType SuccessAudit `
-Newest 50 `
-InstanceId 4624,4634 `
-ComputerName $env:COMPUTERNAME |
Select-Object -Property TimeGenerated,EventID,Message -PipelineVariable myEvent |
Foreach-Object -Process {
convertTo-Json -InputObject #{
TimeGenerated = (Get-Date $myEvent.TimeGenerated)
EventID = $myEvent.EventID
Message = $myEvent.Message.Substring(0, $myEvent.Message.IndexOf("`r"))
} -Depth 1
}
Hope I'm not late for the game. This one example works for me (Get-Service, more than 1 properties having embedded 'collections' of data)
Get-Service |
Select-Object
Name,
Status,
...
and then in the next lines in your script, the next object(s) that you want expanded should be like this
#{Name="CustomCol01";Expression={$_.ServicesDependedOn} },
#{Name="CustomCol02";Expression={$_.DependentService} }
In the example, the 2 offending objects that I need expanded are ServicesDependedOn and DependentService
So yeah by custom making new columns it expands whatever Objects for you
Tested works even when redirecting the final output to a csv like this
... > myfile.csv
This is what I'm running:
Get-Childitem $("C:\Powershell Tests\Group 1") -Recurse -Force | where { -not$_.PSIsContainer } | group name -NoElement | sort name > "C:\Powershell Tests\Group 1.txt"
I'm later using this text file and comparing with the names in another to see what he differences are between the two.
In the text file I'm getting the name truncated with "..."
What can I add so that it doesn't truncate so that I can compare?
PowerShell outputs objects, not text.
If you want to output the file's names, then select the names and output them:
Get-ChildItem "C:\PowerShell Tests\Group 1" -Recurse -Force |
Where-Object { -not $_.PSIsContainer } |
Select-Object -ExpandProperty Name |
Sort-Object -Unique |
Out-File "C:\Powershell Tests\Group 1.txt"
Notes:
you don't need the subexpression operator, $( ), for the parameter to Get-ChildItem.
I removed your call to Group-Object. (It looked to me like you want a sorted list of unique file names.)
I am trying to get some stats about our code. This works fine for one module:
function countTestCases($path=$pwd) {
Get-ChildItem $path -Recurse -Include *.java | Where-Object {-not $_.PSIsContainer } | Select-String "extends ComponentTestCase", "extends DatabaseDependentTestcase" | Group-Object Pattern | Select-Object Count
}
but I want run this across all modules to get a CSV output like this:
module,#ComponentTestCase,#DatabaseDependantTestCase
module1,20,30
module2,12,1
unfortunately, if I add
| Select-Obejct Count
it doesn't work (although Name does). not sure how to get around this without writing too much code...
I couldnt simpler find a way.. but this seems to works
Get-ChildItem $path -Recurse -Include *.cs | Select-String "int", "string" | Group-Object Pattern -AsHashTable | foreach {
new-object psobject -Property #{
int = $_['int'].Count;
string = $_['string'].Count;
module = 'mymodulename'}
} | select module, int, string
The output looks like
module int string
------ --- ------
mymodulename 19 78
I'm using string and int as my patterns, but you'll have to replace it for yours
It works (at least for me). Is it perhaps because this data is right aligned and you don't notice it on the far right side of your console? Also, rather than use select, you can pick off "just" the property value with a Foreach cmdlet e.g.:
Get-ChildItem $path -Recurse -Filter *.java | Where {!$_.PSIsContainer } |
Select-String "extends ComponentTestCase","extends DatabaseDependentTestcase" |
Group-Object Pattern | Foreach {$_.Count}
Select-Object creates a whole new object to contain just the properties you selected from the incoming object so a lot of the time it is overkill. Also, I would recommend using the Filter parameter on Get-ChildItem over Include as Fiter is quite a bit faster.