Bugs Bunny
Bugs Bunny

Reputation: 385

Powershell copy files with creation date equals given date

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

Answers (2)

user2674513
user2674513

Reputation:

When working with PowerShell, there are two things to remember.

  1. PowerShell is object-oriented.
  2. PowerShell uses pipelines.

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.

What objects are being compared?

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.

Let's get our values to be the same type.

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.

Solving the problem with the date comparison.

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

Final Answer

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

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

Related Questions