Unable to compare the integer with the operator in powershell? - powershell

Unbale to compare the interger value in powershell using the -gt or -ge operator
Iam trying to get the latest number of files as a count in to a int variable. After i got the count, i need to check if it is greater than n number. But it doesn't look the value is comparing.
[int]$count_of_Files= Write-Host (Get-ChildItem $source_dir | Measure-Object).Count
if($count_of_Files -gt 3){Write-Host "True
"}
The count_of_files value is 6. But when i ran the if condition to compare the value > 3 , the output "True" not printing
Appreciate if anyone can help on this?

When creating a variable, do not use the Write-Host command ever, it will not assign it to the variable thus making it a NULL variable. Also try not to use strings for a Boolean when you can use $True or $False
[int]$count_of_Files = (Get-ChildItem $source_dir | Measure-Object).Count
IF($count_of_Files -gt 3){
$True
} Else {
$False
}
Comment Answer: Normally you should ask a new question if it is not related to your initial question, but since it is a simple adjustment of the original code, please see below.
# Get files only from $source_dir
$Files = Get-ChildItem $source_dir -File
# Created if statement to check if there are more than 3 files in the $source_dir
IF($Files.Count -gt 3){
# Assigns the top 3 files to $files_to_keep with most recent at the top
$files_to_keep = $Files | Sort-Object LastWriteTime -Descending | Select-Object -first 3
}

Related

How to download an Outlook attachments based on specific file name within the 24 hrs?

I'm trying to download attachments within emails based on file name that have been received within the last 24 hour AND are the first match. The first match is in-case a second email with the same filename is received and needed to be output to the location. The files are received to the inbox typically once a day but there are times where it'll have to be handled via the 'latest received'. So wit that said, when there is a match, the code supposed to grab the files and put the first matched files to the location and then stop / terminate the script.
However, it doesn't seem to take the time factor into account at all. At this point my code finds the first matched two files based on the filename, and dumps them into the location. Then it keeps overwriting the files as it finds older files with the same name within the inbox.
In this latest build / attempt, I'm using $limit = (Get-Date).AddDays(-1) as well as -and ($_.CreationTime -lt $limit) in my code. I've tried a number of methods but nothing seems to work.
$account = 'blah#stihlse.com'
$targetFolder = 'inbox'
$f = $account.Folders | ? { $_.Name -match 'inbox'};
$email = $f.Items| Sort-Object ReceivedTime -Descending | Select-Object -First 1
$limit = (Get-Date).AddDays(-1)
$filepath = "\\servername\home\blah\Documents\blah's emails"
$ol = New-Object -comobject outlook.application
$ns = $ol.GetNamespace('MAPI')
$acct = $ns.Folders[$account]
$acct.Folders[$targetFolder].Items | foreach {
if ($_.ReceivedTime -match $email -and ($_.CreationTime -eq $limit)) {
$_.attachments |
foreach {
Write-Host "attached file: ",$_.filename
If ($_.filename -match 'BlahCompletions' -or $_.filename -match 'BlahCertifications'){
$_.saveasfile((Join-Path $filepath $_.FileName))
}
}
}
}
You use CreationTime -eq $limit. -eq means equal. So it only works if the CreationTime is the exact same microsecond as $limit. What you are looking for is -gt (greater than) or -ge (greater or equal).
The other problem is $_.ReceivedTime -match $email. It is trying to -match the ReceivedTime to an regex. But the regex you provide is the whole $email. Take a look at about_Comparison_Operators
In the code you are iterating over all items in the folder:
$acct.Folders[$targetFolder].Items | foreach {
if ($_.ReceivedTime -match $email -and ($_.CreationTime -eq $limit)) {
Which is really is not a good idea if you have a large number items in the folder. Instead, you need to use the Find/FindNext or Restrict methods of the Items class. Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
For example, to get only items that has attachments onboard you can use the following condition:
query ="#SQL=" & chr(34) & "urn:schemas:httpmail:hasattachment" & chr(34) & "=1"

Powershell - Declaring paths with "$_.pdf" in it

As title says.
I have several if-statements with "Test-Path" in it so it'd be much better if I just declare the variables right away.
$jobs = Get-ChildItem d:\Path\* -recurse -include *.pdf,*.idx |
Select-Object -expand basename |
Sort-Object
$jobs | foreach-object{
if ((test-path d:\Path\$_.idx) -and (test-path d:\path\$_.pdf)){
move-item d:\Path\$_.idx d:\Path
move-item d:\path\$_.pdf d:\Path
}
else {
....
}
}
The file name is varying all the time. That's why I'm using "$_.pdf" for example. This is just a simple example. Add even one more file extension to this and yeah. The code functions like "If pdf and idx basenames are true/equal, move them"
This works completely fine, it's just that putting in the paths for each if statement makes it more confusing.
Any help would be appreciated. Thanks in advance!
Test-Path can take an array of items to be tested. When used so, it will return an array of boolean values. Should that array contain at least one $false, there is at least one missing file. If there isn't, all the files are present.
An example is like so,
# Create a few test files
set-content foo.idx ''
set-content foo.dpf ''
set-content foo.pub ''
# Instead of foo, you'd populate $s with file's basename
# and use a foreach loop
$s ="foo"
# Test if the trio exists. Note variable $s that contains the basename
if( (Test-Path #(".\$s.idx", ".\$s.dpf", ".\$s.pub")) -contains $false){
"nay" # Go here if there was at least one false
}else{
"aye" # go here if all were true
}
# Output
aye
# Change one extension, so trio doesn't exist
if( (Test-Path #(".\$s.idx", ".\$s.dpf", ".\$s.bub")) -contains $false) {
"nay" # Go here if there was at least one false
}else{
"aye" # go here if all were true
}
# Output
nay
I'm dumb.
I just have to put $path\$_.pdf there. thats it

Powershell issue with do while loop

I've got a simple bit of code that looks for a string in a series of log files.
If it finds the string, it should exit the loop (nested inside another loop as part of a function) with $buildlogsuccess = 'True'
If it can't find the string, it should exit and return $buildlogsuccess = 'False'
The select-string statement itself works, however it looks like there's something wrong with the below code:
$logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
$count = ($logArr).count
Foreach ($log in $logArr) {
Do {
$count -= 1
$buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
If (($buildlogsuccess)) {break}
} while ($count -gt '0')
}
When one of the logs has the string, the loop finishes and should return $buildlogsuccess as 'True'.
If I check $log it shows the file that I know has the string (in this instance C:\build\Logs\Installer1.log).
Strangely, at this point $count shows as having a value of -1?
If I take the string out of that file and run again it also exits and returns the correct variable value (and shows the $log variable as the last file in $logArr as expected), but this time $count shows as -24.
My code is also returning $buildlogsuccess as 'False' when the string is present in one of the log files.
Re-tested [bool](select-string -path $log -simplematch $buildstring) by manually populating $log (with a file that has that string) and $buildstring and get 'True' as expected when using
[bool](select-string -path $log -simplematch $buildstring)
Note: Variables it uses:
$buildstring = "Package
'F:\xxx\Bootstrap\apackage\Installsomething.xml' processed
successfully"
Any help identifying where I've gone wrong would be appreciated.
Your code can be greatly simplified:
$buildlogsuccess = Select-String -SimpleMatch -Quiet $buildstring C:\build\Logs\install*.log
The above assumes that there are no directories that match install*.log; if there's a chance of that, pipe the output of Get-ChildItem -File C:\build\Logs -Filter install*.log to Select-String instead.
Do-while will first do the thing, then check the while statement. You're iterating over n files. It doesn't check the value of $count before it executes that portion.
So let's say the first file does not contain the string you're looking for. It will (correctly) decrement the $count variable to zero, and then it moves on to the next $log in $logArr.
Now for each next file in the folder it will decrement $count, and then exit the loop when it sees that $count is not greater than 0.
I don't know why you're using the do-while loop at all here
Thanks Norsk
I over-complicated for myself.
This worked:
$logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
$count = ($logArr).count
Foreach ($log in $logArr) {
$buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
If ($buildlogsuccess) {break}
}

How to rename files with sequential even and odd numbers in PowerShell?

I would like to know how I can rename the files from a specific folder with a sequence of only even and odds numbers in PowerShell. E.g. Folder1: pag_001.jpg, pag_003.jpg, pag_005.jpg.... pag_201.jpg , Folder2: pag_002.jpg, pag_004.jpg, pag_006.jpg.... pag_200.jpg. It is because I have a document that was scanned first the odds pages and secondly the even pages, therefore their file names are in a consecutive sequence from 1 to 201. Then I separated one half of the files which are the odds pages in a new place: Folder1, and the second half,the even pages in the Folder2. That is why I would like change the names first and the join again together with their new names.
I have tried this based in a similar post:
At the moment I could generate even number sequences like that:
ForEach ($number in 1..100 ) { $number * 2}
and odd numbers like that:
ForEach ($number in 0..100 ) { $number *2+1}
and wanted apply the sequences generated before to rename my files like that:
cd C:\test\Folder1
$i = $number * 2
Get-ChildItem *.jpg | %{Rename-Item $_ -NewName ('pag_{0:D3}.jpg' -f $i++)}
but it doesn't works! Any suggestions are welcome
Regards,
Your $i++ adds 1 each time, this is why it also add even numbers,
You can create array of Odd Numbers then use the $i++ to step one item in the array, like this:
$path = "C:\test\Folder1"
$oddNumbersArray = 0..100 | % {$_ *2 +1}
$i = 0
Get-ChildItem $path -Filter *.jpg | % {Rename-Item $_ -NewName ("pag_$($oddNumbersArray[$i]).jpg") ;$i++}
For Even Numbers change the $oddNumbersArray line to {$_ *2}
Bunch of ways to do this. For mine we add each index as a member so that it is more easily accessible in the rename item script block.
$index = 0
Get-ChildItem $path -Filter "*.jpg" | ForEach-Object{
$index = $index +2
$_ | Add-Member -Name "Index" -MemberType NoteProperty -Value $index -PassThru
} | Rename-Item -NewName {'pag_{0:D3}.jpg' -f $_.Index} -WhatIf
Using Add-Member in a ForEach-Object we update the value of index and then add it as a property of the same name. Then in your rename-item scriptblock we can call that property. Remove the -WhatIf after you verified the new names are what you wanted. Switch $index between 0 and -1 for even and odd respectively.
Another method using a global index variable and mitigating the pipeline by using calculated properties to create the pipeline variables that Rename-Item uses.
$path = "C:\Temp\csv"
$global:index = 0 # Use -1 for odd
Get-ChildItem $path -Filter "*.csv" |
Select-Object #{Name="Path";Expression={$_.FullName}},
#{Name="NewName";Expression={$global:index = $global:index + 2; 'pag_{0:D3}.jpg' -f $global:index}} |
Rename-Item -WhatIf

Renaming a new folder file to the next incremental number with powershell script

I would really appreciate your help with this
I should first mention that I have been unable to find any specific solutions and I am very new to programming with powershell, hence my request
I wish to write (and later schedule) a script in powershell that looks for a file with a specific name - RFUNNEL and then renames this to R0000001. There will only be one of such 'RFUNELL' files in the folder at any time. However when next the script is run and finds a new RFUNNEL file I will this to be renamed to R0000002 and so on and so forth
I have struggled with this for some weeks now and the seemingly similar solutions that I have come across have not been of much help - perhaps because of my admittedly limited experience with powershell.
Others might be able to do this with less syntax, but try this:
$rootpath = "C:\derp"
if (Test-Path "$rootpath\RFUNNEL.txt")
{ $maxfile = Get-ChildItem $rootpath | ?{$_.BaseName -like "R[0-9][0-9][0-9][0-9][0-9][0-9][0-9]"} | Sort BaseName -Descending | Select -First 1 -Expand BaseName;
if (!$maxfile) { $maxfile = "R0000000" }
[int32]$filenumberint = $maxfile.substring(1); $filenumberint++
[string]$filenumberstring = ($filenumberint).ToString("0000000");
[string]$newName = ("R" + $filenumberstring + ".txt");
Rename-Item "$rootpath\RFUNNEL.txt" $newName;
}
Here's an alternative using regex:
[cmdletbinding()]
param()
$triggerFile = "RFUNNEL.txt"
$searchPattern = "R*.txt"
$nextAvailable = 0
# If the trigger file exists
if (Test-Path -Path $triggerFile)
{
# Get a list of files matching search pattern
$files = Get-ChildItem "$searchPattern" -exclude "$triggerFile"
if ($files)
{
# store the filenames in a simple array
$files = $files | select -expandProperty Name
$files | Write-Verbose
# Get next available file by carrying out a
# regex replace to extract the numeric part of the file and get the maximum number
$nextAvailable = ($files -replace '([a-z])(.*).txt', '$2' | measure-object -max).Maximum
}
# Add one to either the max or zero
$nextAvailable++
# Format the resulting string with leading zeros
$nextAvailableFileName = 'R{0:000000#}.txt' -f $nextAvailable
Write-Verbose "Next Available File: $nextAvailableFileName"
# rename the file
Rename-Item -Path $triggerFile -NewName $nextAvailableFileName
}