wildcard in array - arrays

How can I use the 1709 as a wildcard? The value 1709 is stored in an array as $MoveItem.Version, but I can't figure out how do a -like, when the value comes from an array, as I can't put in a wildcard *. I also tried to do a match.
The file name looks like this: REFW10-X86-1709_01-12-2017.wim.
The below code works fine, but I would like to automate it, so everything comes from the array. Is that possible?
Get-ChildItem -Path $OSPathTemp -Recurse | Where {
($_.Name -eq $MoveItem.File) -and
($_.Name -like "*1709*")
} | Select-Object -ExpandProperty FullName
$MoveItem.Version contains 1607,1706,1709. I would like to choose only the one with 1709. The final output should look like this:
foreach ($MoveItem in $MoveItems) {
Get-ChildItem -Path $OSPathTemp -Recurse | Where {
($_.Name -eq $MoveItem.File) -and
($_.Name -like $MoveItem.Version)
} | Select-Object -ExpandProperty FullName
}
The Array looks like this:
$MoveItem = #(
[pscustomobject]#{File="REFW10-X86-1709_01-12-2017.wim";Version=1709}
[pscustomobject]#{File="REFW10-X86-1706_01-12-2017.wim";Version=1706}
)

So you have a hash table (or similar) named $MoveItem that has a .File property that is a filename, and you have a .Versions property that's a string array?
Test name: REFW10-X86-1709_01-12-2017.wim
Get-ChildItem -Path $OSPathTemp -Recurse |
ForEach-Object {
If ($_.Name -match '-\d{4}_') { $Version = $Matches[0] }
If ($Version -in $MoveItem.Versions -and
$_.Name -eq $MoveItem.File) { $_.FullName }
}

Related

Interpreting an extension with a wildcard IN an array

Why does this work:
$VideoExtensions = #('.mp4','.mov','.mpg','.mts','.3g2','.3gp','.avi','.mkv','.flv','.wmv')
$Files = Get-ChildItem -LiteralPath $PSScriptRoot -Recurse | Where-Object {
$_.Extension -match '.jp*' -or
$_.Extension -in $VideoExtensions
}
But not this:
$PicExtensions = #('.jp*','.png')
$VideoExtensions = #('.mp4','.mov','.mpg','.mts','.3g2','.3gp','.avi','.mkv','.flv','.wmv')
$Files = Get-ChildItem -LiteralPath $PSScriptRoot -Recurse | Where-Object {
$_.Extension -in $PicExtensions -or
$_.Extension -in $VideoExtensions
}
The .jp* wildcard is completely ignored. If I used -like will it catch files that are not exactly .png? I'm iffy about using -like operators.
I would strongly recommend using regular expressions instead of lists of strings for something like this.
$PicExtensions = 'jp.*|png'
$VideoExtensions = 'mp4|mov|mpg|mts|3g2|3gp|avi|mkv|flv|wmv'
$Files = Get-ChildItem -LiteralPath $PSScriptRoot -Recurse | Where-Object {
$_.Extension -match "^\.(${PicExtensions})$" -or
$_.Extension -match "^\.(${VideoExtensions})$"
}
If you wanted to continue using lists of strings (not recommended) you'd have to compare each element individually (which is bound to perform very poorly), because the -contains and -in operators allow only exact matches whereas you want to do wildcard matches.
$Files = Get-ChildItem -LiteralPath $PSScriptRoot -Recurse | Where-Object {
$ext = $_.Extension
($PicExtensions | Where-Object {$_ -like $ext}) -or
($VideoExtensions | Where-Object {$_ -like $ext})
}
You could just specify multiple patterns in the path, if it didn't have to be literal.
$pic = echo *.jp* *.png
$vid = echo *.mp4 *.mov *.mpg *.mts *.3g2 *.3gp *.avi *.mkv *.flv *.wmv
get-childitem -path ($pic + $vid) -recurse

Using two arrays to create registry keys/values

Trying to automate our font installation process for new PCs.
To install fonts, Windows adds the .ttf, .otf, etc. file to C:\Windows\Fonts and then creates a corresponding registry key in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts. A typical registry key would look like this:
Arial (TrueType) | Arial.ttf
To automate this, I've made two arrays using Get-ChildItem:
$names = Get-ChildItem -Path "C:\corp\install\fonts" | Select-Object name | Out-String | ForEach-Object {$_ -Replace "----","" ` -Replace "Name","" ` -Replace ".otf","" ` -Replace ".ttf","" } | ForEach-Object { $_.Trim() }
$files = Get-ChildItem -Path "C:\corp\install\fonts" | Select-Object name | Out-String | ForEach-Object {$_ -Replace "----","" ` -Replace "Name","" } | ForEach-Object { $_.Trim() }
Each $name in $names will be the name of the registry key, and each $file in $files will be the data for that registry key.
How would I go about doing this? I've attempted to use hash tables, PSObjects, nested ForEach loops, all to no avail. I have had difficulty finding anything on here and elsewhere that matches this situation exactly.
Error checking is not really necessary since there will always be a corresponding value.
REVISED FINAL SOLUTION:
Write-Host "Installing corporate fonts..."
Copy-Item -Path "C:\corp\install\fonts\*" -Destination "C:\Windows\Fonts" -Force -Recurse
$fontList = #()
$fonts = Get-ChildItem "C:\corp\install\fonts" | Select-Object -ExpandProperty Name
ForEach ( $font in $fonts ) {
$fontList += [PSCustomObject] #{
Name = $font -Replace ".otf","" ` -Replace ".ttf",""
File = $font
} |
ForEach-Object {
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" -Name $_.Name -Value $_.File
}
}
I must admit I don't fully understand your question so forgive me if this response is way off base, but it this what you're looking for? A table with both pieces of data in one?
Function CreateVariables {
$namevariables = #()
$filenames = ( Get-ChildItem "C:\corp\install\fonts" ).name
Foreach ( $name in $filenames ){
$namevariables += [PSCustomObject] #{
Name = $name -Replace "----","" ` -Replace "Name","" ` -Replace ".otf","" ` -Replace ".ttf",""
File = $name -Replace "----","" ` -Replace "Name",""
}
}
Return $namevariables
}
CreateVariables
Piping both name and value to set-itemproperty seem impossible. Foreach-object seems the way to go.
$path = 'hklm:\software\microsoft\windows nt\currentversion\fonts'
[pscustomobject]#{name='a name';value='a value'} |
foreach { set-itemproperty $path $_.name $_.value -whatif }
What if: Performing the operation "Set Property" on target "Item: HKEY_LOCAL_MACHINE\software\microsoft\windows nt\currentversion\fonts Property: a name".
You may prefer using this vbscript-like method to install fonts:
https://www.mondaiji.com/blog/other/it/10247-windows-install-fonts-via-command-line

Function return array in PowerShell

I have a problem when I'm trying to return an array from a PowerShell function.
My function:
function filter-SWCluster {
param($Path, $FolderList)
$OldSWCluster = New-Object System.Collections.ArrayList
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* | sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending | Select-Object -skip 3 | ForEach-Object { $OldSWCluster.Add($Path + "\" + $_) }
}
Write-Output $OldSWCluster
}
The function call:
$FilerSWCluster = filter-SWCluster $NetworkPath $SWCluster
The output I get:
0 1 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.2 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.1
The output I want and need would be:
\\server.domain\C$\TEMP\Folders\Testcluster_1.0.2 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.1
I need just the paths. I know there will already be some solutions, but please excuse me. I didn't find one which was working for me or I were to dumb to use it right (could be).
You could also wrap the Add method with the [void] class accelerator. It will hide any output, like this:
function filter-SWCluster {
param($Path, $FolderList)
$OldSWCluster = New-Object System.Collections.ArrayList
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* | sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending | Select-Object -skip 3 | ForEach-Object { [void]$OldSWCluster.Add($Path + "\" + $_) }
}
Write-Output $OldSWCluster
}
wOxxOm already provided you a solution to your problem. However, consider to just return the path using a simple select. You also don't have to join the path since the FullName property already contains the full path:
function filter-SWCluster {
param($Path, $FolderList)
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* |
sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending |
Select-Object -skip 3 |
select -ExpandProperty FullName
}
}

Assign all child paths in the parent directory to an array

I am trying to assign all child paths of files in a directory to an array but not assigning the directories.
I am using the following command:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | % { Write-Host $_.FullName }
The output is printed to the console and not saved in the variable.
Any idea way?
The reason it is writing to the console is because you are saying Write-Host. If you use Write-Output instead, it will save to the variable.
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | % { Write-Output $_.FullName }
Or try using the "Select-Object" instead of write host.
It would look like this:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | select-object -expand FullName
The console output from Write-Host is only displayed, not returned.
You will need to save the value in a variable first, then you can print it:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer };
$a | % { Write-Host $_.FullName }

Powershell - Variables Array's - Finding Folders then Files in Folder

I really need some help with Powershell, complete novice in Powershell
I have the command below, which outputs a list of paths searching for folder called "xyz" created multiple times on a share, used as a variable
$FOLDERLISTS = (Get-ChildItem \\server\share -Recurse | Where-Object { ( $._PSIsContainer -eq $true) -and ($_.Name -like "xyz" -and ( $_.mode -match "d") | % { Write-Host $_.FullName })
How can I use the multiple folder paths, can I set this as a variable?
Basically I just want to get the folder paths, then run another Get-ChildItem against each folder path the above command outputs, so if it was a single variable the command would looks like;
Get-ChildItem "#ABOVECOMMAND" -Recurse | Where-Object ( !($_.PSIsContainer) -and $_.lenght -le 1000000 )
Can I somehow use ForEach for this to run over the multiple paths?
foreach ($FOLDERLIST in $FOLDERLISTS)
{
Get-ChildItem -Recurse | Where-Object { !($_.PSIsContainer) -and $_.lenght -le 1000000 }
}
Or
$FOLDERLISTS | ForEach-Object{
Get-ChildItem -Recurse | Where-Object { !($_.PSIsContainer) -and $_.lenght -le 1000000 }
Or just export the paths to a text file and import into the command? Completely stuck.
Your first try should be more like this:
foreach ($FOLDERLIST in $FOLDERLISTS)
{
Get-ChildItem $FOLDERLIST -Recurse | Where-Object { !($_.PSIsContainer) -and $_.lenght -le 1000000 }
}
OR your second try like this:
$FOLDERLISTS | ForEach-Object{
Get-ChildItem $_ -Recurse | Where-Object { !($_.PSIsContainer) -and $_.lenght -le 1000000 }

Resources