Powershell копирует файлы с датой создания, равной заданной дате

#powershell

#powershell

Вопрос:

Я пытаюсь скопировать файлы с датой создания, равной заданной дате, но безуспешно, переданные аргументы являются текущей датой 2/12/2020 и создали несколько файлов сегодня, но они ничего не копируют, чего мне не хватает?

код

 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
    }
    
}
 

Комментарии:

1. $_.Name это имя файла без пути, не так ли?. Вы пытаетесь скопировать из корневого каталога файлы, которые вы перечислили в другом месте (в c:logs ).

Ответ №1:

вам нужно время усечения

 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
    }
    
}
 

Ответ №2:

При работе с PowerShell следует помнить о двух вещах.

  1. PowerShell является объектно-ориентированным.
  2. PowerShell использует конвейеры.

В той мере, в какой вы сможете придерживаться этих правил, у вас будет больше возможностей, и ваша работа будет проще.

Вы проделали хорошую работу с конвейером.

Вот несколько инструментов для изучения объектной стороны вещей.

Какие объекты сравниваются?

Здесь я буду использовать формат даты для своего языка. Я вижу, что вы используете день-месяц-год.

Вы можете использовать Get-Member для исследования объектов в 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…
...
 

Здесь мы видим, что наша строка даты равна a System.String .


Я хотел бы знать, что это за тип объекта CreationTime .

 > 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)
...
 

Здесь мы видим, что CreationTime это a System.DateTime .

Давайте сделаем так, чтобы наши значения были одного типа.

Если вы хотите выполнить сравнение строк в стиле оболочки, вас ничто не остановит. Но тогда вам не хватило бы всего богатства объектов PowerShell.

В принципе, мы сравниваем две даты. Итак, давайте преобразуем наш строковый ввод в объект DateTime.

 > [DateTime] "12/2/2020"

Wednesday, December 2, 2020 12:00:00 AM
 

Обратите внимание, что когда мы вводим приведение строки даты, подобной "12/2/2020" DateTime объекту, время автоматически заполняется для свойств Hour , Minute , и Second . По умолчанию используется полночь.

Решение проблемы со сравнением дат.

Давайте посмотрим на один из объектов DateTime из моего предыдущего запроса.

 > Get-ChildItem -File | Select-Object -First 1 | ForEach-Object CreationTime

Saturday, September 26, 2020 10:57:33 AM
 

В моем конкретном случае в моем файле отображается дата Saturday, September 26, 2020 10:57:33 AM .

Объекты DateTime всегда включают время. В нашем случае время нас не волнует. Итак, один из способов решить нашу проблему — установить для временной части наших объектов одинаковое значение. Затем, когда мы сравниваем два объекта, только часть даты может повлиять на результат.

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
 

Окончательный ответ

Итак, давайте используем [DateTime] приведение типов и Date свойство, чтобы исправить нашу функцию.

Здесь я также добавил параметры со значениями по умолчанию. Мы можем вызывать findLogs так же, как и раньше. Но у нас также есть возможность изменить способ работы функции без необходимости ее перезаписи.

Я также использовал свойство FullName для упрощения копирования файла.

 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  }
}
 

В моей среде я смог скопировать один из своих букмарклетов в папку резервной копии:

 $a = "C:UsersMichaelDesktopBookmarklets"
$b = "C:UsersMichaelDesktopBackup" 

findLogs -searchDate "12/3/2020" -source $a -destination $b -nameLike "Mark*"