я НЕ хотите «удалить файлы старше X дней». Если бы я хотел это сделать, я бы просто выбрал один из тысяч сценариев, которые уже были написаны для этой цели, и не стал бы задавать такой тривиальный вопрос о ServerFault.
я ДЕЛАТЬ хотите удалить все файлы, кроме N последних, в определенной папке.
Фон: удаленная система настроена на выгрузку периодических архивных файлов в общую папку на сервере Windows. Эти файлы имеют соглашение об именах ГГГГММДД-ччмм.ext. В случае сбоя процесса архивирования я не хочу, чтобы сценарий очистки удалял файлы только потому, что они старше, чем на много дней. Невозможно настроить удаленную систему на очистку файлов в процессе архивирования.
Так, например, при запуске сценария может быть 10 файлов, может быть 7 файлов, может быть 5 файлов в папке. Мне нужно всегда хранить как минимум 5 самых последних, независимо от того, сколько им лет.
Можно ли это сделать с помощью PowerShell?
РЕДАКТИРОВАТЬ: желательно игнорировать файлы или папки, не соответствующие соглашению об именах. Другие файлы и папки не следует удалять, и они не должны сбивать с толку скрипт (в результате остается менее 5 архивных файлов).
Использование: yourScript.ps1 -Path path \ to \ run \ against [-NumberToSave N]
param([String]$Path,[Int32]$NumberToSave=5)
$items = Get-ChildItem "$Path\*.ext" |
Where-Object Name -match "\d\d\d\d\d\d\d\d-\d\d\d\d\.ext" |
Sort-Object Name -Descending
if ($NumberToSave -lt $items.Count)
{
$items[$NumberToSave..($items.Count-1)] | Remove-Item
}
Я не ожидаю, что это действительно лучше, чем у @John, я просто сделал это, чтобы попробовать параметры, регулярное выражение, а не использовать цикл. Сопоставление с регулярным выражением действительно имеет возможное преимущество в исключении других файлов с .ext, которые не соответствуют формату (например, 20130504-1200.txt.ext, 20.ext), но сомнительно, что это применимо.
Я был поражен, узнав, что если $ NumberToSave = $ items.Count, тогда требуется оператор if, иначе его бы там не было. Технически:
$items[$numberToSave..$items.Count] | Remove-Item
работает нормально (PowerShell, похоже, не вызывает ошибки, если вы ссылаетесь за пределы массива, он просто обрабатывает и игнорирует его?), но это казалось потенциально запутанным.
$n = x
$items = Get-ChildItem path_to_folder\*.ext
$items |
Sort-Object Name -Descending |
Select-Object -Last ($items.count - $n) |
Foreach-Object { Remove-Item $_ }
Друг предоставил этот сценарий:
# Defines how many files you want to keep?
$Keep = 5
# Specifies file mask
$FileMask = "*.ext"
# Defines base directory path
$Path = "F:\path\to\backups\"
# Creates a full path plus file mask value
$FullPath = $Path + $FileMask
# Creates an array of all files of a file type within a given folder, reverse sort.
$allFiles = @(Get-ChildItem $FullPath) | SORT Name -descending
# Checks to see if there is even $Keep files of the given type in the directory.
If ($allFiles.count -gt $Keep) {
# Creates a new array that specifies the files to delete, a bit ugly but concise.
$DeleteFiles = $allFiles[$($allFiles.Count - ($allFiles.Count - $Keep))..$allFiles.Count]
# ForEach loop that goes through the DeleteFile array
ForEach ($DeleteFile in $DeleteFiles) {
# Creates a full path and delete file value
$dFile = $Path + $DeleteFile.Name
# Deletes the specified file
Remove-Item $dFile
}
}
# Get all the items in `C:\Archive`
Get-ChildItem -Path 'C:\Archive' |
# Skip directories
Where-Object { -not $_.PsIsContainer } |
# Only get files that match YYYYMMDD-HHMM.ext format
Where-Object { $_.Name -match '\d{8}-\d{4}.ext' } |
# Sort them by name, from most recent to oldest
Sort-Object -Descending -Property Name |
# Keep the first five items
Select-Object -Skip 5 |
Remove-Item -WhatIf
Я делал это в Bash раньше, и вы, возможно, сможете перевести это в PowerShell. Лично я администратор Linux и недостаточно разбираюсь в Windows / PowerShell, чтобы делать это сам.
#!/bin/bash
# Directory with backups in need of cleaning
bkps_dir="/opt/bkps/hosting.madyork.com"
# Make sure that there are at least 7 days worth of backups to avoid removing
# the only backups left.
if [ "$(/bin/find "${bkps_dir}" -maxdepth 1 -type d | /usr/bin/wc -l)" -lt 8 ]; then
echo "Less than 8 backups found!"
echo "Will not delete anything!"
echo "Exiting..."
exit 1
fi
/bin/find "${bkps_dir}" -maxdepth 1 -type d -mtime +7 -print0 | /usr/bin/xargs -0 /bin/rm -rf
Извините, что я не мог быть более полезным.
Изменить: я также разместил это здесь на случай, если администратору Linux понадобится аналогичная информация.