Interpreting an extension with a wildcard IN an array - arrays

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

Related

wildcard in array

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 }
}

PowerShell - rename all files in local path\script directory and all subfolders

so, trying to rename any file found in the current script directory and all subfolders. Doesn't want to work. This is what I have so far...what am I doing wrong? The issue I'm having is that it is not renaming files in the subfolders.
<# Renames all files in the working directory to have an extension of .hd #>
$files = Get-ChildItem $PSScriptRoot -Recurse | Where-Object {$_.Extension -match ".jpg|.jpeg|.png|.bmp|.gif|.3gp|.mp4|.webm|.mkv"}
ForEach ($file in $files) {
$filenew = $file.Name + ".hd"
Rename-Item $file $filenew
}
you are passing a filesystem object to path parameter of rename-item instead of a string path.
change this :
Rename-Item $file $filenew
to this:
Rename-Item -Path $file.fullname -NewName $filenew
You could also simplify your script to this:
Get-ChildItem -Path $Path -Include *.jpg,*.png,*.mp4 -Recurse |
Rename-Item -NewName { $_.Name + '.hd' } -WhatIf
Note: remove -whatif to apply the rename action
Anyway, so $file.Name contains the extension so you need $file.Basename
$files = Get-ChildItem $PSScriptRoot -Recurse | Where-Object {$_.Extension -match ".jpg|.jpeg|.png|.bmp|.gif|.3gp|.mp4|.webm|.mkv"}
ForEach ($file in $files) {
$filenew = $file.BaseName + ".hd"
Rename-Item $file $filenew
}

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 }

Powershell log deleted files

The script searches all folders and subfolders and delete the oldest file when the number of files is>5. Everything works fine, but I want also log all the delete Files as a record in a log-file.
How can I log the deleted files ?
Here the Script.
$path = "C:\test\1"
$keep = 3
$strLogFileName = "c:\test\yourlogfile.log";
$dirs = Get-ChildItem -Path $path -Recurse | Where-Object {$_.PsIsContainer}
foreach ($dir in $dirs) {
$files = Get-ChildItem -Path $dir.FullName | Where-Object {-not $_.PsIsContainer -and $_.name -like "*.zip"}
if ($files.Count -gt $keep) {
$files | Sort-Object CreationTime -desc| Select-Object -First ($files.Count - $keep) | Remove-Item -Force
***{write-host “Deleting File $File” -foregroundcolor “Red”; Remove-Item $File | out-null}***
}
}
First you will need a log-message type function in your script that will log the message to a .log file. Then chekc if the file exists and if not then create a file.
Then just before you delete your file with Remove-Item command you can use Log-Message function to log message to the log file.
% { (Log-Message "Deleting File $_"); $_ }
Complete script
$path = "C:\test\1"
$keep = 3
$strLogFileName = "c:\test\yourlogfile.log";
function Log-Message
{
Param ([string]$logtext)
Add-content $strLogFileName -value $logtext
}
$dirs = Get-ChildItem -Path $path -Recurse | Where-Object {$_.PsIsContainer}
foreach ($dir in $dirs) {
$files = Get-ChildItem -Path $dir.FullName | Where-Object {-not $_.PsIsContainer -and $_.name -like "*.zip"}
if ($files.Count -gt $keep) {
$files | Sort-Object CreationTime -desc| Select-Object -First ($files.Count - $keep) |
% { $dt=get-date;(Log-Message "Deleting File $_ on $dt");$_ }| Remove-Item -Force
}
}
You've got a good start here:
write-host “Deleting File $File” -foregroundcolor “Red”
Unfortunately Remove-Item doesn't have any output that you can mooch from, but you've already made your own output message so we can just build from that. You can pipe any output to a file by using Out-File. The append flag will attach the new content to the end of the file, and you do not have to check if the file exists.
Write-Output “Deleting File $File” | Out-File -Append logfile.txt
You don't even have to include Write-Output, if you want a shorter line.
Here is an example that shows where you need to add code. I've marked existing code with "...", and I've moved the deletion message into a variable so that you can reuse it at another location. This assumes that you've stored the selected filename in a variable.
...
if ($files.Count -gt $keep)
{
...
$message = "Deleting File $File at "+(Get-Date)
$message | Out-File -Append logfile.txt
}
...

Comma delimited input for a powershell function

I currently have a function that I made that gets a list of all files in a directory and then adds them to an array called $FileListArray.
I want to add an option that lets me specify the file extensions to exclude from the arrary so that I could call the function as follows ListFiles -FilesToList "c:\test" –exclude “avi,txt,bmp” and this would then ignore files with any of the file extensions I have put in.
My Function so far
Function ListFiles($FilesToList){
$FileListArray = #()
Foreach($file in Get-ChildItem $FilesToList -Force -Recurse | Where-Object {$_.attributes -notlike "Directory"})
{
$FileListArray += ,#($file.name,$file.fullname,$File.Extension)
}
}
Listfiles -FilesToList "c:\tools"
Try this:
Function ListFiles($Path,$Exclude)
{
Get-ChildItem -Path $FilesToList -Force -Recurse |
Where-Object {!$_.PSIsContainer -and $_.Extension -notmatch ($Exclude -join '|') }
}
Listfiles -Pathc:\tools –Exclude avi,txt,bmp

Resources