I would like to write the directory names of several folders in an array. However, only all directory names with a date <today should be read. The directory names contain a date in this form * YYYYMMDD *
So I would have to do the following:
Borrow the date
Write the date in the form of YYYYMMDD in a variable
Read out directory names and check against the variable
Write data to an array ... do something ...
Can someone tell me how I can solve this with Powershell please?
Thank you
Start by retrieving all the candidate directories, then use Where-Object to extract the date part and test that it describes a date prior to today:
# Define threshold
$Today = (Get-Date).Date
# Go through all candidate directories
$oldDirectories = Get-ChildItem .\path\to\root\folder -Directory |Where-Object {
$dt = 0
# Test if directory name contains 8 consecutive digits describing a valid date
if($_.Name -match '(\d{8})' -and [datetime]::TryParseExact($Matches[1], 'yyyyMMdd', , $null, 'None', [ref]$dt)){
# We only want the ones with a date prior to today
$dt.Date -lt $today
}
else{
# Not containing a properly formatted date, we're not interested
$false
}
}
# Now we can extract the names
$oldDirectoryNames = #($oldDirectories.Name) # or #($oldDirectories |Select -Expand Name)
Do these directorynames start with the date?
yes
What do you mean by Borrow the date? Is that the date of today or what?
Determine the Date, Yes of today.
I read out the date accordingly and wrote it in a variable:
$Timestamp = ([datetime]::now).tostring("yyyyMMdd")
Now I want to read out all directory names which have got a Date < 1 Day and would like to process it in a foreach for further processing
Understandable?
Related
I’m using PowerShell with a script to convert a .CSV raw data file into more manageable data format with separate columns, a cleaner view etc. And because the source file with the raw data is in US date and time format (e.g. 11/23/21, 1:00 PM), then if the PC is in that same US format the conversion process runs perfectly as should with 0 errors. BUT, if the PC is in a different country date and time format, then PowerShell shows errors in red in the process.
When the PC is in other DateTime format I see the main error is:
"Parse" with "1" argument(s): "String was not recognized as a valid DateTime."
And the problem is the PC where this will be used is not in US format (only changed to US format for testing), so could someone here please help me to add to the conversion process the syntax or sentence/s to simply specify directly in the code a fixed format that keeps a static output format independently about the PC clock date and time format, and if one of the inputs into the file is “11/23/21, 1:00 PM” then to specify in the code you want the output in the format “dd-MMM-yyyy hh:mm” to have a result like “23-Nov-2021 01:00 PM”
The code section in the script used for the conversion is:
…
$data = $csvData | ? {$_ -match "\(DTRE"}
dtreFileData = New-Object System.Collections.Generic.List[PSCustomObject]
foreach ($item in $data)
{
$null = $item.Strategy -match "\(DTRE\|(.*)\)"
$v = $Matches[1] -split '\|'
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$dtreData = [PSCustomObject]#{
'DateTime' = ([datetime]::Parse($item.'Date/Time'))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
}
$null = $dtreFileData.Add($dtreData)
$null = $dtreAllData.Add($dtreData)
}
$dtreFileData | Export-Csv -Path (Join-Path (Split-Path -Path $f -Parent) ($outFile + '.csv')) -Force -NoTypeInformation -Encoding ASCII
…
Example of raw source data (in the CVS file are dozens of lines like the next one):
...(DTRE|49.0|48.2);...;11/23/21, 12:58 PM...;
...(DTRE|52.1|52.0);...;11/23/21, 1:00 PM...;
...
...
And the Output looks like:
I tried with DateTime examples in other posts from here (stackoverflow.com) to adjust the code to work in a PC without US date and time format and to get the DateTime format result described above. Examples like:
'DateTime' = ([datetime]::Parse($item.'yyyy-MM-dd:HH:mm:ss'))
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss'))
…
$culture = [Globalization.CultureInfo]::InvariantCulture
…
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss', $culture))
…
But with these examples PowerShell shows the error “Cannot bind argument to parameter 'InputObject' because it is null”
Update after the answer from #Seth:
When trying next modification of the code, with the PC system date format in “24-Nov-21” and leaving the rest as above:
…
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$cultureInfo= New-Object System.Globalization.CultureInfo("es-ES")
$dtreData = [PSCustomObject]#{
'DateTime' = ([System.DateTime]::Parse($item.'Date/Time', $cultureInfo))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
…
then, PowerShell shows the next errors:
As it has been explained it's a good idea to fix the CSV to have a better dateformat. An example would be ISO 8601 which can be used with Get-Date -Format "o".
That said Get-Date relies on C# stuff in the background. So you can use C# code to read that in a particular culture. As you know the origin culture this should work. Fixing the timestamp is still a better idea.
$cultureInfo= New-Object System.Globalization.CultureInfo("en-US")
$dateString = "11/23/21, 12:58 PM";
$dateTime = [System.DateTime]::Parse($dateString, $cultureInfo);
Get-Date -Format "o" $dateTime
With this example code you'd assign $dateString the value of $item.' Date/Time' and the result you likely want would be the result of Get-Date. So you'd assign $dtreData.'DateTime' the result of that Get-Date call. Alternatively it is possible to use the .NET DateTime Object to directly convert to a particular culture. For instance by calling $dateTime.ToString((New-Object System.Globalization.CultureInfo("en-ES"))). Though not all that useful you could also pass the format identifier to this method. This might be relevant if you want to avoid creating additional objects. A somewhat unnecessary call would be $dateTime.ToString("o", (New-Object System.Globalization.CultureInfo("en-ES"))) (as format o is the same in every culture).
I have a specific date "2021/11/28", i want the list of files from example filenames(below) whose file name is greater than 2021/11/28. remember not the creation time of the file names.
"test_20211122_aba.*"
"abc_20211129_efg.*"
"hij_20211112_lmn.*"
"opq_20211130_rst.*"
I'm expecting to get
"abc_20211129_efg.*"
"opq_20211130_rst.*"
Really appreciate your help.
You don't strictly need to parse your strings into dates ([datetime] instances): Because the date strings embedded in your file names are in a format where their lexical sorting is equivalent to chronological sorting, you can compare the string representations directly:
# Simulate output from a Get-ChildItem call.
$files = [System.IO.FileInfo[]] (
"test_20211122_aba1.txt",
"abc_20211129_efg2.txt",
"hij_20211112_lmn3.txt",
"hij_20211112_lmn4.txt",
"opq_20211130_rst5.txt"
)
# Filter the array of files.
$resultFiles =
$files | Where-Object {
$_.Name -match '(?:^|.*\D)(\d{8})(?:\D.*|$)' -and
$Matches[1] -gt ('2021/11/28"' -replace '/')
}
# Print the names of the filtered files.
$resultFiles.Name
$_.Name -match '(?:^|.*\D)(\d{8})(?:\D.*|$)' looks for (the last) run of exactly 8 digits in each file name via a capture group ((...)), reflected in the automatic $Matches variable's entry with index 1 ($Matches[1]) afterwards, if found.
'2021/11/28"' -replace '/' removes all / characters from the input string, to make the format of the date strings the same. For brevity, the solution above performs this replacement in each loop operation. In practice, you would perform it once, before the loop, and assign the result to a variable for use inside the loop.
I have txt file with date value, line by line
I try to compare them to today date in powershell but its not working
$DateTimeNow = (Get-Date).ToString('dd/MM/yyyy')
$data2 = get-content "output.txt"
$z= #()
foreach($line2 in $data2)
{
if($line2 -match $DateTimeNow){
write-host "same date"
}
}
the compare with "match" not work, I have try -eq and = but nothing better.
Have you any idea what I am doing wrong ?
The input dates all use 2-digit notation for the year (20 for 2020), but your string representing today's date uses 4-digits. Change to the appropriate format and it will work:
$DateTimeNow = Get-Date -Format 'dd/MM/yy'
I created a small scrip that have do to a couple of thinks.
get string from description field from user in specific container
take part of this string (substring method) that holds date information
convert this string to date format
compare this formated string with a current date - 30 days and do sth
The problem is that comparing is not working correctly. I tried do recognise date that is older than 30 days and do something but i see that comparison not always work. sometimes it does not recognize that date is less then - 30 days from current day
Script below
$DateMaxTime = (Get-date).AddDays(-30)
$DateFormatMaxTime = Get-Date $DateMaxTime -Format dd/MM/yyyy
$getData = get-ADUser -Filter * -Properties * -SearchBase "OU=Disabled,OU=Control,OU=x,OU=x,DC=x,DC=x,DC=x" `
|where {$_.Description -like "LEFT*"} |select name,samaccountname,description
Foreach ($Data IN $getData){
$DataPart = $null
$DataPart=$Data.description
$DatePart= $DataPart.substring(5,10)
$FinalDate = [datetime]::ParseExact($DatePart,'dd/MM/yyyy',$null)
$FinalDateFormat = Get-Date $FinalDate -Format dd/MM/yyyy
If ($FinalDateFormat -lt $DateFormatMaxTime ){ Write-Host "$($Data.samaccountname), $($Data.description) moved to deleteMe" }
else{ Write-Host "$($Data.samaccountname), $($Data.description) still in disabled" }
}
Below output shows me the wrong results (as example i did it for one user - >
Based on this logic the value $FinalDateFormat that hold date -> 31-12-2018 is less then value $DateFormatMaxTime that hold this date -> 25-06-2019 but it still applies else statement ...
I am not sure why, i did something wrong with date conversion ?
I put the comments as the answer:
I would compare the datetime versions of the dates rather than the string versions.
If ($FinalDate -lt $DateMaxTime)
Running
get-date -format
makes them strings.
$finaldate.gettype(); $datemaxtime.gettype()
shows the types. They are [datetime], not [string] like the other two.
I want yesterday's date as "MMdd", like "0418" today's date is "0419".
I tried this:
$d = (Get-Date).AddDays(-1) | select -Property Month,Day
$e = $d.Day
$d = $d.Month
$total = "$d" + "$e"
Write-Host $total
But the output was "418".
As you can see, this is a three-letter string, but I want a four-letter one. Because I want to search files they have that format and created a day before.
The date object has a method ToString, which allows you to specify the format:
$d = (Get-Date).AddDays(-1);
$d.ToString("MMdd");
I am calling this on April the 20th, and the output is
0419
See this link for a description of the available date format strings.