How to mapping a string with array using powershell? - arrays

I have an array and need to mapping a string inside a file by using the array then output the matched string to a file.
I tried it but when I found 2 match string in the file, in the output file only has 1 string.
$ArrayString = "Network controller TPX","Network controller SXCM", "Adapter controller CNA"
$GetFile = Get-Content .\File
foreach($string in $ArrayString ){
$GetFile | Select-String -Pattern $string | Out-File .\result.txt -Force
}
The content inside the file looks like this:
Network controller SXCM
Disable
*Enable
Admin Passwordfrom Startup Menu
*Disable
Enable
Adapter controller CNA
Disable
*Enable
Verify on every boot
*Disable
Enable
in some case the string in $ArrayString will matched 1 in the $Getfile and also matched 2 string.
Anyone can help me please. Thank you so much

The main issue with your code is that Out-File is inside the loop and without an -Append switch so each loop iteration is overwriting the file. Unfortunately, even if there is no match, the file would be overwritten due to the way Out-File was coded, seems like it opens the file stream in it's begin block which, shouldn't be the case and is one of many reasons why Set-Content should be the go to cmdlet when writing to a plain text file.
To explain the issue with Out-File visually:
# Create a temp file and write some content to it:
$file = New-TemporaryFile
'content' | Set-Content $file.FullName
Get-Content $file.FullName # => content
# `Process` block doesn't run on `AutomationNull.Value`,
# so, the expected would be, if nothing is received from pipeline,
# don't touch the file:
& { } | Set-Content $file.FullName
Get-Content $file.FullName # => 'content' // as expected
# Trying the same with `Out-File`
& { } | Out-File $file.FullName
Get-Content $file.FullName # => null // file was replaced
# dispose the file after testing...
$file | Remove-Item
A few considerations, Select-String can read files so Get-Content is not needed, and -Pattern can take an array of patterns to match. Here is the simplified version of your code.
$ArrayString = "Network controller TPX", "Network controller SXCM", "Adapter controller CNA"
Select-String -Path .\file.txt -Pattern $ArrayString |
ForEach-Object { $_.Matches.Value } | Set-Content result.txt

Related

How to search Powershell array for specific strings and use this result in a copy-item -include script

I'm trying to create a synchronization script in Powershell so that my applications in MDT are being copied on a regular basis to our main file server, based on the folder name (in MDT, applications are in one folder, where our main server has applications split depending on the department who uses them).
From what I read on the web, the best way would be to populate an array with "Get-ChildItem", which I kinda figured how to do (see code below).
After the array is populated though, I don't know how to search that array for specific results, nor do I know how to use those results with copy-item.
In a nutshell, here's what I need to do: Build an array using "Get-ChildItem", query the resulting array for specific folders, and have those folders be copied to specific destinations.
Here's the code I have so far:
$arr = Get-ChildItem \\slmtl-wds02.domain.inc\deploymentshare$\applications |
Where-Object {$_.PSIsContainer} |
Foreach-Object {$_.Name}
$sourcepath = \\slmtl-wds02.domain.inc\deploymentshare$\applications
$destSLARC = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLARCMTL
$destSLMTL = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLMTL
$destSLGLB = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLGLB
$destSLTECH = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLTECH
Thanks in advance for your help :)
$sourceLocation = "c:\analysis\"
$targetLocation = "c:\analysisCopy\"
$included = #("folder1", "folder2")
$result = #()
foreach ($i in $included){
$result += get-ChildItem $sourceLocation -filter $i | Where-Object {$_.PSIsContainer}
}
$result | foreach-Object { copy-item $_.FullName -Destination $targetLocation -Recurse}
Hope this works change the path D:\ to your desired path enter the name of folder you looking for
$Keyword=[Microsoft.VisualBasic.Interaction]::InputBox("Enter your Query")
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
Get-ChildItem D:\ -recurse | Where-Object {$_.PSIsContainer -eq $fasle -and $_.Name -match "$keyword"} | Copy-Item -Destination d:\test

Loop/Cycle through Subdirectories and determine file count in each

I have the directory E:\NugetRoot\NugetServer where I need to cycle through the subdirectories on this path and within the packages folder within that subdirectory I need to count the files ending in .nupkg and output them to a cvs file named d:\monitoring\NugetStatistics and each time the script is run, it should append to the file.
Count the files ending in .nupkg in "C:\NugetRoot\NugetServer\\**\Packages" for each folder. (I need to Loop through the ** folders and count each file ending on .nupkg)
Output in cvs file with two columns: one showing the "**" folder name & the other showing the file count.
First find all the *.nupkg files using Get-Childitem with the recurse flag to get all files in sub folders, then filter the results using a regex to exclude any where the final folder is not called Package. Then use another regex to extract the previous folder name, feed that in to a Group-Object to get the count and then into a Export-Csv which includes the append flag.
cd E:\NugetRoot\NugetServer
Get-ChildItem -Filter *.nupkg -Recurse | ? {
$_.DirectoryName -match '\\Packages$'
} | % {
$_.DirectoryName -Replace '^.*\\([^\\]+)\\Packages$', '$1'
} | Group-Object | Select Name, Count | Export-Csv outfile.csv -Append -NoTypeInformation
cd "C:\NugetRoot\NugetServer\\**\Packages"
$a = Get-ChildItem -Name
foreach ($i in $a) {
$b = (Get-ChildItem -Recurse -Force -Include .nupkg -Path $i | Select-Object -ExpandProperty Name).Count
$i + "`t" + $b
}
Here's what I have so far. It displays the server name, ProjectgroupID(or folder name), but get error for package count. Also, I am having trouble getting the average file size as well, I commented those out:
$folders = gci C:\NuGetRoot\NugetServer -Directory
foreach($folder in $folders){
#{ServerName=$env:COMPUTERNAME;
ProjectGroupID = $folder.Name;
NuGetPackageCount = (gci $folder.FullName\packages -Include '*.nupkg') | %{$_.Size}.Count;
#AverageSize= Measure-Object (listof sizes) -Average
} #| Export-Csv -Path c:\temp -NoTypeInformation -Append
}
Measure-Object -Average

Output overwrites previous entry in file

If I get rid of the last line Out-File "HDDresults.txt" then the output shows on the screen in the correct format, just a long list of all the computers and their serial numbers. If I try to output to a file, each computer entry overwrites the previous entry, so when the script finishes executing there is only the last entry in the file. How do I get the file output to look exactly like the console output?
I don't know how to script. I just copied and pasted from multiple sources until I got something that works.
Import-Module ActiveDirectory
Get-ADComputer -filter * | Foreach-Object {
Get-WmiObject Win32_PhysicalMedia -computer $_.name |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"
}
You simply need to set the -Append flag:
Out-File "HDDresults.txt" -Append
By default, Out-File overwrites the content of the file for each write operation. This will cause it to add text to the end of the file instead.
While adding the -Append argument makes the script function, I think a better fix to this is to move the Select statement and all that follows it outside of the ForEach loop so that the file is written once with all of the information once it is processed, and not having to open the file, write to it, close it, open it again, write to it, close it again, for each system.
Import-Module ActiveDirectory
Get-ADComputer -filter * |
Foreach-Object { Get-WmiObject Win32_PhysicalMedia -computer $_.name } |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"

Read entries from text file into a variable in PowerShell

I hope someone can help me. I am pretty new to PowerShell and can't really script it myself with the exception of looking at existing code and modifying it.
I have found a PowerShell script that reports file share permissions for a specific share and recurses through the subfolders returning their permissions as well.
My problem is I need to do this with a lot of shares so would like to be able to provide the script with a text file containing the share names. I know I need to do a for each loop and read the names of the shares in a text file into an array but I don't know how to do this. I guess it's pretty simple for someone with more experience.
This is the script i have used with single entry.
http://mywinsysadm.wordpress.com/2011/08/17/powershell-reporting-ntfs-permissions-of-windows-file-shares/
#Set variables
$path = Read-Host "Enter the path you wish to check"
$filename = Read-Host "Enter Output File Name"
$date = Get-Date
#Place Headers on out-put file
$list = "Permissions for directories in: $Path"
$list | format-table | Out-File "C:\scripts\$filename"
$datelist = "Report Run Time: $date"
$datelist | format-table | Out-File -append "C:\scripts\$filename"
$spacelist = " "
$spacelist | format-table | Out-File -append "C:\scripts\$filename"
#Populate Folders & Files Array
[Array] $files = Get-ChildItem -path $path -force -recurse
#Process data in array
ForEach ($file in [Array] $files)
{
#Convert Powershell Provider Folder Path to standard folder path
$PSPath = (Convert-Path $file.pspath)
$list = ("Path: $PSPath")
$list | format-table | Out-File -append "C:\scripts\$filename"
Get-Acl -path $PSPath | Format-List -property AccessToString | Out-File -append "C:\scripts\$filename"
} #end ForEach
Sorry for the noob question. I plan to learn more when I have a bit more time but any help now would be massively appreciated.
Thanks in advance.
If you have a share name on each line within your text file can put all the shares into an array like this:
$path = "C:\ShareNames.txt"
$shareArray = gc $path
To access the first share you can use this syntax:
$shareArray[0]

Powershell: Trying To Match a Variable Against an Array using Get-Content

I am retrieving the hosts file on a server with 5 DNS entries:
C:\Windows\System32\drivers\etc\hosts
Mine looks like this after the comments:
127.0.0.1 infspcpd8tx8e.rtmphost.com
127.0.0.1 infspkbpef39p.rtmphost.com
127.0.0.1 infspo99vn3ti.rtmphost.com
127.0.0.1 infspqx6l10wu.rtmphost.com
127.0.0.1 infspvdkqjhkj.rtmphost.com
In my hosts file I see them as 5 lines on top of eachother, but when I paste it here it has a space inbetween. This is the same when I use get-content on that file, but I wouldn't expect that to stop me.
So I have an array that is gotten like so:
$ACCOUNTS = Get-ChildItem "D:\cyst\accounts\" | select name
I then try to see if there are duplicate entries in the hosts file by checking the $accounts variable against the array I got containing the hosts file.
foreach ($rtmp in $ACCOUNTS) {
$HostsFile = Get-Content C:\Windows\System32\drivers\etc\hosts | ForEach-Object {[System.Convert]::ToString($_)}
#$rt[string]$data = $HostsFile
[string]$rtmpfull = $rtmp.name + ".rtmphost.com"
if ($HostsFile -contains $rtmpfull) { Write-Host "Host found in hosts file moving on..." }
else { echo "wrong"
}
}
It never matches and always returns false, I can't match anything.. please help - is it a type issue? I've googled this for DAYS but now i'm desperate and posting here.
I think you can probably speed that up by just dispensing with the foreach.
(Get-Content C:\Windows\System32\drivers\etc\hosts) -match [regex]::escape($rtmpfull)
Should match the entire hosts file at once.
$ACCOUNTS = Get-ChildItem "D:\cyst\accounts\"
foreach ($rtmp in $ACCOUNTS){
$found=$FALSE
foreach ($line in (gc C:\Windows\System32\drivers\etc\hosts)){
if(($line -match $rtmp) -and ($found -eq $TRUE)){
echo "$($matches[0]) is a duplicate"
}
if (($line -match $rtmp) -and ($found -eq $FALSE)){
echo "Found $($matches[0]) in host file..."
$found=$TRUE
}
}
}
Not elegant, but it will do the job.
This test:
if ($HostsFile -contains $rtmpfull)
is looking for $rtmpfull to match an entire line stored in $HostsFile. You want to check for a partial match like so;
if ($HostsFile | Foreach {$_ -match $rtmpfull})
BTW you can simplify this:
$HostsFile = Get-Content C:\Windows\System32\drivers\etc\hosts | ForEach-Object {[System.Convert]::ToString($_)}
to:
$HostsFile = Get-Content C:\Windows\System32\drivers\etc\hosts
By default, Get-Content will give you an array of strings where each element of the array corresponds to a line in the file.

Resources