Read entries from text file into a variable in PowerShell - arrays

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]

Related

How to mapping a string with array using powershell?

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

Powershell script to find file age on multiple shares

I'm working on a powershell script to read file attributes filtered by CreationTime on multiple shares. The scripts works, sporadically. It works great when I use a single path but I get mixed results when I add the folders paths to an array. The most disturbing result is when it successfully find and reads all path and then includes everything under c:windows\system32. Same anomaly when shares are empty.
So what I want to accomplish is:
Read list of Shares
Read each share content filtered by 'CreationTime' and 'Archive' attributes.
Save results to a csv file.
if file not empty, write results to event log.
here is my testing code
$Date=(Get-Date).AddHours(-3)
$FolderList = "C:\Software\Scripts\FolderList.txt"
$Folders = get-content $Folderpath
$Filepath = "C:\Software\Scripts"
$filename = "$Filepath\" + $timer + "OldFiles.csv"
foreach ($Folder in $Folders)
{
Get-ChildItem -Path $Folder -Recurse -Force | Where-Object { $_.CreationTime -lt $Date -and $_.Attributes -eq "Archive"} | Select Attributes, CreationTime, Fullname | Export-Csv -Path $filename -NoTypeInformation
}
if ( (get-childitem $filename).length -eq 0 )
{
exit
}
else{
#Write to OpsMgr Log
$Message = get-content $filename
Write-EventLog -LogName "Operations Manager" -Source "Health Service Script" -EventID 402 -EntryType Information -Message "Old files found. $Message"
}

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

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