Reputation: 385
I'm trying to copy files with creation date equals to given date with no luck
args passed is current date 2/12/2020
and created a few files today but it copy nothing
what am I missing?
CODE
function findLogs ($searchDate)
{
Get-ChildItem c:\logs | Where-Object{ $_.CreationTime -eq $searchDate -and $_.Name -like "logs*" } | ForEach-Object {
$fileName = $_.Name
Copy-Item "c:\$fileName" -Destination c:\backup
}
}
Upvotes: 1
Views: 2519
Reputation:
When working with PowerShell, there are two things to remember.
To the extent you can stick to these rules, you will have more options and your work will be easier.
You've done a good job with the pipeline.
Here are some tools to investigate the object side of things.
Here I'll use the date format for my locale. I see you're using day-month-year.
You can use Get-Member to investigate objects in PowerShell.
> "12/2/2020" | Get-Member
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Clone Method System.Object Clone(), System.Objec…
CompareTo Method int CompareTo(System.Object value),…
Contains Method bool Contains(string value), bool C…
...
Here we see that our date string is a System.String
.
I'd like to know what type of object CreationTime
is.
> Get-ChildItem -File | Select-Object -First 1 | ForEach-Object CreationTime | Get-Member
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
Add Method datetime Add(timespan value)
AddDays Method datetime AddDays(double value)
AddHours Method datetime AddHours(double value)
...
Here we see that CreationTime
is a System.DateTime
.
If you want to do shell-style string comparisons, there is nothing stopping you. But then you would be missing all the richness of PowerShell objects.
In principle, we're comparing two dates. So, let's convert our string input to a DateTime object.
> [DateTime] "12/2/2020"
Wednesday, December 2, 2020 12:00:00 AM
Notice that when we type cast a date string like "12/2/2020"
to a DateTime
object, a time is automatically filled in for the Hour
, Minute
, and Second
properties. By default, midnight is used.
Let's look at one of the DateTime objects from my earlier query.
> Get-ChildItem -File | Select-Object -First 1 | ForEach-Object CreationTime
Saturday, September 26, 2020 10:57:33 AM
In my particular case, my file shows the date Saturday, September 26, 2020 10:57:33 AM
.
DateTime objects always include the time. In our case, we don't care about the time. So, one way to solve our problem is to set the time portion of our objects to the same value. Then, when we compare two objects, only the date portion can affect the outcome.
Let's look at the properties and methods of DateTime to see if there is anything that can help us.
The first property on the list is Date. That seems like it might be interesting. Let's look at that.
The description of Date is:
Gets the date component of this instance.
A new object with the same date as this instance, and the time value set to 12:00:00 midnight (00:00:00).
This sounds like it might be useful.
Remember, when we type cast our string date, we got a DateTime object with the time portion set to midnight.
Here, we're taking a date and returning the same date with the time set to midnight.
Now we have a method of setting both our string input and file creation times to the same value. So, when we compare those DateTime objects, we'll just be comparing the date portions. This will solve our problem.
Let's demonstrate the necessary code.
> [DateTime] "12/2/2020"
Wednesday, December 2, 2020 12:00:00 AM
> Get-ChildItem -File | Select-Object -First 1 | ForEach-Object { $_.CreationTime.Date }
Saturday, September 26, 2020 12:00:00 AM
So, let's use [DateTime]
type casting and the Date
property to fix our function.
Here, I've also added parameters with default values. We can call findLogs
in the same way as before. But we also have the option of changing the way the function works without having to rewrite it.
I've also used the FullName property to simplify the file copy.
function findLogs ([string] $searchDate, [string] $source = "c:\logs", [string] $destination = "c:\backup", [string] $nameLike = "logs*" )
{
Get-ChildItem -Path $source -File |
Where-Object { ($_.CreationTime.Date -eq (([DateTime] $searchDate).Date)) -and ($_.Name -like $nameLike) } |
ForEach-Object { Copy-Item -Path $_.FullName -Destination $destination }
}
In my environment, I was able to copy one of my bookmarklets to a backup folder:
$a = "C:\Users\Michael\Desktop\Bookmarklets"
$b = "C:\Users\Michael\Desktop\Backup"
findLogs -searchDate "12/3/2020" -source $a -destination $b -nameLike "Mark*"
Upvotes: 1
Reputation: 856
you need truncate time
function findLogs ($searchDate)
{
Get-ChildItem c:\logs | Where-Object{ ([DateTime]::Parse($_.CreationTime.ToString("yyyy-MM-dd") -eq $searchDate -and $_.Name -like "logs*" } | ForEach-Object {
$fileName = $_.Name
Copy-Item "c:\$fileName" -Destination c:\backup
}
}
Upvotes: 1