PowerShell Test-Path -exclude - powershell

I need to perform a check on a target folder, and check if the file is from today and has more than 5kb
The below command provide a bool value based on the existence of the file using the today date, but I would like to add also an exclusion like -gt5kb
I tried to use -Exlcude but I'm not sure on how it work.
$integration = Test-Path 'C:\Users\EA\Desktop\CATS HTML*' -NewerThan (Get-Date -UFormat "%d/%m/%Y")
Do you have any advice on how can I include also the size check in the same statement?

This is not possible with the Test-Path cmdlet.
The exclude parameter is defined as follow:
Specifies items that this cmdlet omits. The value of this parameter
qualifies the Path parameter. Enter a path element or pattern, such as
"*.txt". Wildcard characters are permitted.
You will need a second method to perform the check. Here an example using the Get-Item cmdlet:
if (Get-Item 'yourfile.html'| Where-Object Length -gt 5kb) {
# do something
}

Related

Test-Path fails but doesn't do else

I am trying to test several paths and if any fail, create the paths.
$subFolders = "$sortByProject$projectName\Originals", "$sortByProject$projectName\Pulled", "$sortByProject$projectName\Retouched", "$sortByProject$projectName\Uploaded"
if(!(Test-Path -Path "$sortByProject$projectName", "$subFolders")){
New-Item -ItemType Directory -Path "$sortByProject$projectName", "$subFolders"
}
The test finds "$sortByProject$projectName" exists but "$subFolders" fails, so output appears like:
True
False
I would think since a false is returned, it would move to the new-item command and build all four requested folders (.\originals, .\pulled, .\retouched and .\uploaded). All the variable are properly named and return the desired path when called independently. I think the mess up is because there are multiple items assigned to $subfolders, but I don't understand why.
I also think this code is sloppy and would love to learn a better way to do a multiple path test and create any of the missing paths.
You don't need to explicitly test the existence of your directory paths:
Just use New-Item's -Force switch in combination with -ItemType Directory, which will create the specified directories on demand - including parent directories - while leaving existing directories alone (and returning directory-info objects describing the preexisting / newly created directories).
New-Item -Force -ItemType Directory -Path $subFolders
As for what you tried:
Your Test-Path command returns an array of Booleans, and PowerShell considers any 2+-element array $true in a Boolean context - irrespective of its element values; see the bottom section of this answer for a summary of the PowerShell's to-Boolean coercion rules.
-Path "$sortByProject$projectName", "$subFolders" has two problems:
Not only is double-quoting variable values passed as command arguments never necessary in PowerShell, in the case of the array variable $subFolders using "$subFolders" turns the array into a single string containing the (stringified) elements separated with spaces.
If you correct this immediate problem - by using
-Path $sortByProject$projectName, $subFolders - another problem is revealed: you aren then in effect passing a jagged array, whose first element is a string, and whose second element is a nested array, which would break the invocation.
Correcting this problem requires a perhaps non-obvious approach: you must use + rather than , in order to construct a flat array, which in turn requires that the LHS already be an array, which requires using the unary form of ,, the array constructor operator, and switching to an expression, enclosed in (...), the grouping operator:
-Path (, $sortByProject$projectName + $subFolders)
$subfolders | where {-not (Test-Path $_)} | Foreach-Object { New-Item -ItemType Directory -Path $_ }

Removing the front part of a string based on an specific character. (\)

I first create my array with a list of files in a directory (and subdirectories) using the Cmdlet Get-ChildItem, and store them in a variable
$PSVariable = (Get-ChildItem -Path "F:\SQL_Backups" -Recurse *.bak).FullName
I echo the variable ($PSVariable), this is my output (as desired):
F:\SQL_Backups\INTRAPORTAL\StoreDevelopment\StoreDevelopment_backup_2021_02_11_003002_3930170.bak
F:\SQL_Backups\INTRAPORTAL\StoreDevelopment\StoreDevelopment_backup_2021_02_12_003002_4780885.bak
F:\SQL_Backups\JDASQL\DEVMOD\DEVMOD_backup_2021_02_10_190002_5130923.bak
F:\SQL_Backups\JDASQL\DEVMOD\DEVMOD_backup_2021_02_11_190003_7621021.bak
Goal:
I need to remove the directory path from each array entries so it only contains the file name that will be stored in a temporary variable within a foreach loop:
StoreDevelopment_backup_2021_02_11_003002_3930170.bak
StoreDevelopment_backup_2021_02_12_003002_4780885.bak
DEVMOD_backup_2021_02_10_190002_5130923.bak
DEVMOD_backup_2021_02_11_190003_7621021.bak
Some will recommend simply using (.Name) in the Get-ChildItem command, but I need the array to have both the path and filename (FullName) as the array's contents are being used for other parts of the function. I'm a novice when it comes to regular expressions and I can't seem to get the results in the goal section. I've even tried using trim() methods, but no luck. Any recommendations would greatly be appreciated. Thank you.
Expanding on what #AdminOfThings recommended, you are making more work for yourself than you need. PowerShell is an object based scripting language, so to succeed you should use its full POWER.
The approach you're taking now is to take only one property from this useful object and then find you need to start slicing and dicing it in order to make it work.
There's an easier way. We love easy here, and the easy way to do this is to take the full object and then pick and chose its properties where it makes sense, like this:
$i = 0
#changed to remove the .FullName at then end
$PSVariable = (Get-ChildItem -Path "F:\SQL_Backups" -Recurse *.bak)
ForEach ($item in $psVariable){
$i++
Write-host "Processing [$($item.Name)], item number $i of $($psVariable.Count)"
Copy-item -Path $item.FullName -Destination C:\temp -WhatIf
}
It gives you meaningful output and then you have the full selection of properties to work with.
The one that makes the most sense to use is just .Name as you reference above. But then you still have .FullName, which includes the qualified path as well.
If you want to see the full selection of properties, try this:
$PsVariable[0] | Format-list *
Offered only as an inferior option to that of FoxDeploy's you can also use Split-Path to get the filename from a path
$PSVariable = (Get-ChildItem -Path "F:\SQL_Backups" -Recurse *.bak).FullName
$PSVariable | Split-Path -Leaf

How do you use Get-Content with the exclude parameter?

I'm learning PowerShell and going through the parameters for Get-Content. I'm not sure how to use -Exclude with Get-Content.
I'm assuming it's supposed to be something like this:
Get-Content myfile.txt -Exclude "some string"
Am I using it wrong because it's not excluding some string in myfile.txt.
The -Exclude parameter does not apply to the content of files.
From the documentation:
-Exclude
Omits the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as "*.txt". Wildcards are permitted.

Test-Path -isValid with wildcards

I am trying to validate paths so I can provide meaningful error logging, and I am running into an issue with wildcards.
This returns False unless there is a folder and something in it, but it should return True.
Test-Path -isValid -path:"C:\Somefolder\*"
And like this doesn't work because -literalPath doesn't interpret wildcards.
Test-Path -isValid -literalPath:"C:\Somefolder\*"
My sense is that I am going to have to test for wildcards, and if found Test-Path -isValid on the parent folder. But then I run into issues with -like because I can't really test for a condition like *.EXT. Which has me thinking the only real answer is a RegEx, but this feels like something so basic I shouldn't really need to resort to a RegEx and I am probably missing something.
Note that for a variety of reasons I am limited to PS v2.
EDIT: To clarify, the actual path is variable. Users provide a path in an XML file, I then validate the path and do something with it. So, it might be that the user wants to delete all TXT files in a certain path. Or all files. Or even all files and subfolders. Thus C:\Somefolder\* needs to be supported. If they had C:\\Somefolder\* or C:Somefolder\* I would want to flag that as an invalid path. But C:\Somefolder\* when Somefolder doesn't exist is not an invalid path, it's a missing folder and I want to flag that as a different error.
Indeed you need a regular expression for validating a path specification. Something like this should work:
$re = '^[a-z]:[/\\][^{0}]*$' -f [regex]::Escape(([IO.Path]::InvalidPathChars -join ''))
'C:\something\*' -match $re # returns $true
The expression will match any string starting with a letter followed by a colon, a forward or backslash, and any number of valid path characters.
Note that consecutive path separators are valid in a path, so C:\\something\* -match $re will evaluate to $true as well, as it should.
If you want to validate actual (existing) paths instead of path specs you can use Get-ChildItem:
function Test-WildcardPath($Path) {
Get-ChildItem $Path -ErrorAction SilentlyContinue >$null
return $?
}
Again, C:\\something\* will evaluate to $true, since consecutive path separators are allowed in a path.
Can you try like this :
Test-Path -IsValid C:\Somefolder
Edit : then why don't you leave out the wildchars for test-path?
$test.Substring(0,($test.length-($test.Split("\")[-1]).length-1))

In function repeat an action for each entered parameter

My main script run once gci on a specified drive via -path parameter , then it does multiple different tables from this output. Here below is a part of my script which does a specific table from an directory specified via -folder parameter, for example :
my-globalfunction -path d:\ -folder d:\folder
It work fine, but only for one entered folder path, the goal of this script is that user can enter multiple folders path and get a tables for each entered -folder parameter value, like this :
This clause in your Where-Object would be the issue:
$_.FullName.StartsWith($folder, [System.StringComparison]::OrdinalIgnoreCase)
The array of folders passed are most likely being cast as one long string which would never match. I had a regex solution posted but remembered a simpler way after looking at what your logic was trying to do.
Simpler Way
Even easier way is to put this information right into Get-ChildItem since it accepts string arrays for -Path. This way I don't think you even need to have 2 parameters since you never again use the results from $fol anyway. Based on the assumption that you were looking for all subfolders of $folder
$gdfolders = Get-ChildItem -Path $folder -Recurse -Force | Where-Object{$_.psiscontainer}
That would return all subfolders of the paths provided. If you have PowerShell 3.0 or higher this would even be easier.
$gdfolders = Get-ChildItem -Path $folder -Recurse -Force -Directory
Update from comments
The code you have displayed is incomplete which is what lead me to the solution that you see above. If you do use the variable $fol somewhere else that you do not show lets go back to my earlier regex solution which would work better in place with what you already have.
$regex = "^($(($folder | ForEach-Object{[regex]::Escape($_)}) -join "|")).+"
....
$gdfolders = $fol | Where-Object{($_.Attributes -eq "Directory") -and ($_.FullName -match $regex)}
What this will do is build a regex compare string with what I will assume is the logic of locate folders that begin with either of paths passed.
Using your example input of "d:\folder1", "d:\folder2" the variable $regex would work out to ^(d:\\folder1|d:\\folder2). The proper characters, like \, are escaped automatically by the static method [regex]::Escape which is applied to each element. We then use -join to place a pipe which, in this regex capture group means match whats on the left OR on the right. For completeness sake we state that the match has to occur at the beginning of the path with the caret ^ although this is most likely redundant. It would match paths that start with either "d:\folder1" or "d:\folder2". At the end of the regex string we have .+ which means match 1 to more characters. This should ensure we dont match the actual folder "d:\folder1" but meerly its children
Side Note
The quotes in the line with ’Size (MB)’ are not the proper ones which are '. If you have issues around that code consider changing the quotes.