У меня за день много файлов с разными именами. Как я могу отфильтровать их по дате в их имени?
Например:
app_20130505.log
app_20130506.log
app_20130507.log
app_20130508.log
app_20130509.log
И мой фрагмент кода:
$RetainedDays = 7
$FileNameRegex = "\w+_(\d+)\.\w+"
$ArchiveBoundary = $(Get-Date -Format yyyyMMdd) - $RetainedDays
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse |
Where-Object { $_.Name -match $FileNameRegex }
У меня есть фильтр регулярных выражений: \w+_(\d+)\.\w+
, который возвращает мне дату в переменной $ Matches, но как я могу объединить их и вернуть список файлов с теми файлами, которые старше 7 дней?
Я понимаю, что это вопрос четырехлетней давности. Но я подумал, что добавлю новый ответ, поскольку в настоящее время нет других одобренных ответов.
Я бы сделал это так, чтобы разобрать дату на фактическую DateTime
объект из имени файла. Тогда вы можете использовать обычные сравнения дат, а не сравнения строк. Самый распространенный способ сделать это - использовать Расчетная недвижимость как часть Select-Object
заявление. В приведенном ниже примере мы добавляем вычисляемое свойство с именем ParsedDate
к существующему выпуску.
$RetainedDays = 7
$FileNameRegex = "\w+_(\d+)\.\w+"
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse |
Select-Object *,@{
L='ParsedDate';
E={ if ($_.Name -match $FileNameRegex) {
$strDate = $matches[1];
[DateTime]::ParseExact($strDate,"yyyyMMdd",$culture)
}
}
} | Where { $_.ParsedDate -lt (Get-Date).AddDays(-$RetainedDays) }
Регулярное выражение на самом деле делает вещи более сложными, чем это могло бы быть необходимо. Если все ваши файлы имеют одинаковый шаблон именования app_ <ДАТА> .log, вы можете пропустить регулярное выражение и упростить, позволив ParseExact
делай всю работу вот так. Вам просто нужно экранировать буквальные символы в строке формата, заключив их в одинарные кавычки.
$RetainedDays = 7
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse | Select FullName,@{
L='ParsedDate';
E={ [DateTime]::ParseExact($_.Name,"'app_'yyyyMMdd'.log'",$culture) }
} | Where { $_.ParsedDate -lt (Get-Date).AddDays(-$RetainedDays) }
Технически говоря, вы также можете выполнить синтаксический анализ даты внутри предложения Where и пропустить промежуточное предложение Select. Но я оставлю это в качестве упражнения для читателя.
Это не очень приятно, но работает! :)
$RetainedDays = 14
$ArchiveBoundary = (Get-Date).AddDays(-$RetainedDays).ToString('yyyyMMdd')
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse |
Where-Object { ($_.BaseName -split '_|\.')[1] -lt $ArchiveBoundary }
Посмотрите, поможет ли это приблизиться к тому, что вы пытаетесь сделать.
$RootPath = "C:\temp"
$ProcessFiles = @()
$RetainedDays = 7
$Today = get-date -format yyyyMMdd
$FileNameRegex = "\w+_(\d+)\.\w+"
foreach ($File in Get-ChildItem -Path $RootPath) {
$match = [regex]::matches($File, $FileNameRegex )
$FileNameDate = $match[0].Groups[1].Value
if (($Today - $FileNameDate) -ge $RetainedDays) { $ProcessFiles += $File }
}
$ProcessFiles