#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 следует помнить о двух вещах.
- PowerShell является объектно-ориентированным.
- 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*"