I have a powershell script that runs and collects information and puts it in a .csv file. A sample of the information looks like what is listed below, with each line starting with a unique server name followed by a random unique identifier in contained a pair of ( ).
"GDR01W01SQ004 (e785754f-eeb1)","1","4","63","NY-TER-PLN-P-5N"
"GDR01L02D001 (4b889a4d-d281)","4","12","129","CO-FDP-STE-NP-5N"
I have a second powershell script that runs and takes this .csv file and its information and formats it into a report with a header and proper spacing.
Can someone please assist me with removing the text in between the ( ) as well as the ( )?
I would like the entries for each line to look like the following:
"GDR01W01SQ004","1","4","63","NY-TER-PLN-P-5N"
Thank you very much in advance!
Here is the script I have been using.
####################PowerCLI Check####################
# Verify whether the PowerCLI module is loaded, if not load it.
if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin VMware.VimAutomation.Core -ErrorAction Stop
}
################### Run Time Section ####################
#This script should be run from a server that has DNS records for all entries in vcenters.txt
$file = get-Content c:\reports\vcenter\vcenters.txt
foreach ( $server in $file) {
Connect-VIserver -Server $server
Get-VM | select Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes | Out-Null
}
# Command for Custom Annotations.
Get-VM | select Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes -expandproperty customfields | Export-Csv -path “c:\reports\vcenter\vcenall.csv” -NoTypeInformation
# Takes vcenall.csv and sorts only the Name and Notes columns and selects all but the custom fields. Capacity Reporting script caprep.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Notes, Name | Select-Object Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes |Export-csv capacity.csv -NoTypeInformation
#Used to remove domain from server name
(Get-Content capacity.csv) | ForEach-Object { $_ -replace ".domain.local", "" } | Set-Content capacity.csv
# Takes vcenall.csv and sorts only the Notes column and selects only the Name and Notes columns. Nimsoft comparison script nimcomp.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Notes | Select-Object Name, Notes | Export-csv nimsoft.csv -NoTypeInformation
# Takes vcenall.csv and sorts only the Name columns and exports all fields. Backup/Restore comparison script bure.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Name | Export-csv bure.csv -NoTypeInformation
I think you need to add more information but just using what you have let try this one approach
Import-Csv C:\temp\test.csv -Header server,1,2,3,4 | ForEach-Object{
$_.server = (($_.server).split("(")[0]).Trim()
$_
}
We import the csv data and assign a header. If you already have one then this parameter can be omitted.
Then we examine each row of data as an object. Change the server data by splitting it up by its spaces. If this data is for server names then it is safe to assume that that everything before the first space is the server name. This approach is dependent on the space being there. We could also use the same logic with the ( but this would be easier if the space was a guarantee.
So we update the server and then send the data back down the pipe with $_.
Sample Output
server 1 2 3 4
------ - - - -
GDR01W01SQ004 1 4 63 NY-TER-PLN-P-5N
GDR01L02D001 4 12 129 CO-FDP-STE-NP-5N
Edit based on comments
Since it is a server display name I changed the logic to split based on the "(". Also using the Split() method instead of the -split operator.
Related
Get-ChildItem 'C:\Users\Zac\Downloads\script test\script test\*.txt' -Recurse | ForEach {(Get-Content $_ | ForEach { $_ -replace '1000', $fileNameOnly}) | Set-Content $_ }
I have been trying to use a simple PowerShell script to replace the 1000 value in my documents with the goal of replacing the value with the name of the .nc1/.txt file it is editing.
For example a file that is called BM3333.nc1 has a line value of 1000 which needs to replace it with BM3333 so on, so forth. This will be used in batch editing.
What is the variable that I use for replacing the 1000 with the file name?
So far, I can get this to run but it doesn't replace the 1000 value, it removes it.
Your problem is that inside the ScriptBlock of a ForEach-Object invocation, the variable is $_ (also known as $PSItem). There is no name for the inner script to get the value from the outer script.
You need to create a unique name in the outer script beforehand. The ScriptBlock argument to ForEach-Object does not need to be a single expression. You can either use multiple lines or a ;.
1..3 | ForEach-Object { $a = $_; 100..105 | ForEach-Object { $_ * $a } }
For your use case, you need this variable to be the name of the file. The values in the outer ScriptBlock are System.IO.FileSystemInfo, which were returned by Get-ChildInfo.
PowerShell makes iterating on work like this very easy; try seeing which properties are available:
Get-ChildItem 'C:\Users\Zac\Downloads\script test\script test\*.txt' -Recurse | Select-Object -First 1 | Format-List *
I need to create a csv file out of values that are spread over many txt files. Here is an example for one of the txt files (they are all formatted the same way and stored in one folder, lets say c:\user\txtfiles):
System: asdf
Store: def
processid: 00001
Language: english
prodid: yellowshoes12
email: asdf#asdf.com
prodid: blueshoes34
some
other
text blabla
The result csv should look like this (i added values from another sample txt just to make it clear):
processid, prodid
00001, yellowshoes12
00001, blueshoes34
00002, redtshirt12
00002, greensocks34
That means that every product ID in the txt should be assigned to the one processid in the txt and added as single line to the csv.
I tried to reach the result as follows:
$pathtofiles = Get-ChildItem c:\user\txtfiles | select -ExpandProperty FullName
$parsetxt = $pathtofiles |
ForEach {
$orderdata = Import-Csv $_ |
Where-Object {($_ -like '*processid*') -or ($_ -like '*prodid*')} |
foreach {
write-output $orderdata -replace 'processid: ','' -replace 'prodid: ',''
}
}
$orderdata
So my intention was to isolate the relevant lines, delete everything that is not wanted, assign the values to variables and build a table out of it. One problem is that if I replace $orderdata from the end of the code into the end of the first foreach-loop nothing is printed. But after deliberating quite a while I am not sure if my approach is a good one anyway. So any help would be very appreciated!
Daniel
I think this is best done using a switch -Regex -File construct while iterating over the files in your folder.
# get the files in the folder and loop over them
$result = Get-ChildItem -Path 'c:\user\txtfiles' -Filter '*.txt' -File | ForEach-Object {
# the switch processes each line of a file and matches the regex to it
switch -Regex -File $_.FullName {
'^processid:\s+(\d+)' { $id = $matches[1] }
'^prodid:\s+(\w+)' { [PsCustomObject]#{'processid' = $id; 'prodid' = $matches[1]}}
}
} | Sort-Object processid, prodid
# output on console screen
$result
# output to CSV file
$result | Export-Csv -Path 'c:\user\txtfiles\allids.csv'
Result on screen:
processid prodid
--------- ------
00001 blueshoes34
00001 yellowshoes12
00002 greenshoes56
00002 purpleshoes88
In my report when I remove the export-csv portion the data is presented correctly onscreen, when I add in the export-csv no data is exported but the file is created. Below is my script along with what the data looks like when script is running (modified) of what the data looks like.
#Get all DHCP Servers
$ServerList = (Get-Content -Path "\\termserv\DHCPServers.txt")
foreach ($server in $serverlist)
{
#Get the scopes from each serve
Get-DHCPServerv4Scope -ComputerName $server | select ScopeID |
#Get the lease information for each scope
ForEach-Object {Get-DHCPServerv4Lease -ScopeId $_.ScopeId -ComputerName
$server -AllLeases |
where {$_.AddressState -like "*Reservation"} | Select-Object
$server,ScopeId,IPAddress,HostName,ClientID,AddressState | Export-
Csv "\\termserv\d$\term\User\Reservations1.csv"
}
}
What the data looks like when exported without export-csv
NOPEDH01 :
ScopeId : 000.11.2.3
IPAddress : 111.22.3.444
HostName : NOPE00112233
ClientID : 00-11-22-33-44-55
AddressState : ActiveReservation
NOPEDH01 :
ScopeId : 000.11.2.3
IPAddress : 111.22.3.445
HostName : NOPE0011223344
ClientID : 00-11-22-33-44-56
AddressState : ActiveReservation
Update: Tried that and still nothing, when I run a modified version of the script locally on my DH servers it functions correctly, but I'm looking at almost 100 DH servers in my environment, see below
Get-DHCPServerV4Scope | ForEach {
Get-DHCPServerv4Lease -ScopeID $_.ScopeID -AllLeases | where
{$_.AddressState -like '*Reservation'}
} | Select-Object ScopeId,IPAddress,HostName,ClientID,AddressState | Export-
Csv "\\termserv\d$\term\$($env:COMPUTERNAME)-Reservations1.csv" -
NoTypeInformation
This is a representation of what you are doing:
Foreach ($Server in $ServerList)
{
Foreach ($Scope in $ScopeList)
{
$Data | Export-csv -Path FileName.csv
}
}
In doing so you are exporting data [(Total Servers) x (Total Scopes per server)] times which is a lot of I/O operations. It is just a logistics issue. You could collect the entire information into a table object before exporting. But that decision is up to you and your particular business needs.
The real issue, however, is that you are doing the export into the same file which essentially over writes whatever you have written before without telling it not to. So only the last export remains which I suspect is somehow blank.
Try using the -Append switch when you export.
$Data | Export-csv -Path FileName.csv -NoTypeInformation -Append
Also I noticed you are using $server variable in the select-object cmdlet where you should only be using the object's property names and not variable names. I do not know if that returns anything as the cmdlet would not know what to do with it, which could also be contributing to the problem.
According to your code you are using Export-Csv within a foreach-object. Generally Export-csv creates a csv file with new data. If data is already present in the csv file then it will overwrite the existing data with new one.
So instead of using
Export-Csv "\\termserv\d$\term\User\Reservations1.csv"
You cand use
Export-Csv "\\termserv\d$\term\User\Reservations1.csv" -Force -Append -NoTypeInformation
Here -Append will append the data in the csv file. Not overwrites.
hey im trying to build a powershell script that will pull a serial number from a remote pc and then match that against an xlsx file which would then match a column against another xlsx file i have gotten to the point where i can pull the remote sn and have everything put in to a csv output but i am having issues matching the data then filtering based on the match and then outputting only what i need im new to scripting so im pretty sure its more my lack of experiance than anything else this is my code so far
$computers = Get-Content c:\script\computerlist.txt
Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber| Format-Table |out-file C:\script\computerinfo.txt
$computerinfo = Import-Excel C:\script\compDB.xlsx
$userinfo = Import-Excel C:\script\userDB.xlsx
$Computerinfo[2].SERIAL -eq
$Computerinfo[2].DATE_ADDED
$Computerinfo[2].OS
$Computerinfo[2].MODEL
$Computerinfo[2].USER
$userinfo[2].NAME_FIRST
$userinfo[2].NAME_LAST
$userinfo[2].NT_USERID
''
'Computer Info'
'----------'
$computerinfo ,$userinfo | Format-Table - | Out-File c:\script\computerinfo.csv
First you need to save the wmi information to a variable:
$WMIinfo = Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber
Then you would need to loop through the spreadsheet and compare to data in Computer spreadsheet. If it matches loop through user spreadsheet for match:
foreach ($CompEntry in $Computerinfo) {
if ($WMIinfo.serial -eq $CompEntry.serial) {
foreach ($UserEntry in $userinfo) {
if ($UserEntry.NT_USERID -eq $CompEntry.USER) {
#output information you want here
}
}
}
I'll try to help you get there.
I created an Excel file called Serial.xslx. Here's what it looks like
SerialNumber DeployedTo
212 Ham
4M24N32 Stephen
I then import this as $list.
$list = import-excel C:\temp\serial.xlsx
Next,to get the Win32_Bios info, so I can grab the SerialNumber property.
$bios = get-WmiObject Win32_Bios
Finally, I'll filter through the $list (which contains the Excel file), and find a row which has a SerialNumber that matches this computers serial number. If I find a matching one, then I grab the .DeployedTo value for that record.
$user = $list | Where SerialNumber -eq $bios.SerialNumber | Select -ExpandProperty DeployedTo
All that remains is to demonstrate that it works.
"the computer with serial $($bios.SerialNumber) is deployed to $user"
>the computer with serial 4M24N32 is deployed to Stephen
Now, you've got two separate excel files, so I would either manually join them into one, or repeat this same basic approach.
This is really PowerShell 101, I realise, but I'm stuck.
I'm trying to iterate through a folder tree, getting each subfolder name and a count of files. No problems there.
The new requirement is to get the ACLs on each subfolder as well. All of this data needs to be output as a CSV file, with a line consisting of each folder name, the file count, and the ACLs in a single string in one field of the CSV (I was going to delimit them with semicolons).
I am open to exporting to XML if the data can be viewed in Excel.
The part where I'm stuck is getting the ACL information into a single string for the CSV.
Get-ACL on each directory shows the data as follows (I'm doing a Select to just get the IdentityReference and FileSystemRights, which is all we're interested in):
IdentityReference FileSystemRights
----------------- ----------------
BUILTIN\Users ReadAndExecute, Synchronize
BUILTIN\Users AppendData
BUILTIN\Users CreateFiles
I would like the output file formatted with one line per subdirectory, similar to
#filecount,folder,perms
51,C:\temp,BUILTIN\Users:ReadAndExecute,Synchronize;BUILTIN\Users:AppendData...
I however can't get any kind of join working to have it presented in this way. I don't care about what combination of delimiters are used (again, must be readable in Excel).
The script, such as it is, is as follows. The output file has its line of data appended with each directory it traverses. I'm sure this isn't very efficient, but I don't want the process consuming all the server memory either. The bits I can't figure out are prepended with ###.
(Get-ChildItem C:\temp -recurse | Where-Object {$_.PSIsContainer -eq $True}) | foreach {
$a = ($_.GetFiles().Count)
$f = $_.FullName
$p = (get-acl $_.FullName).Access | select-object identityreference,filesystemrights
### do something with $p?
Out-File -FilePath c:\outfile.csv -Append -InputObject $a`,$f`,###$p?
}
Since you want all ACEs of a folder mangled into a single line you need something like this:
Get-ChildItem 'C:\temp' -Recurse | ? { $_.PSIsContainer } | % {
# build a list of "trustee:permissions" pairs
$perms = (Get-Acl $_.FullName).Access | % {
"{0}:{1}" -f $_.IdentityReference, $_.FileSystemRights
}
New-Object -Type PSObject -Property #{
'Filecount' = $_.GetFiles().Count
'Folder' = $_.FullName
'Permissions' = $perms -join ';' # join the list to a single string
}
} | Export-Csv 'c:\outfile.csv' -NoType
Repeated appending inside a loop usually guarantees poor performance, so it should be avoided whenever possible. The outer loop creates a list of custom objects, which can then be exported via Export-Csv in a single go.