Script Powershell para excluir arquivos mais antigos (não relativos à data atual)

5

Eu NÃO quero "excluir arquivos com mais de X dias". Se eu quisesse fazer isso, eu escolheria um dos milhares de scripts que já foram escritos para essa finalidade, e eu não me incomodaria em fazer uma pergunta tão trivial no ServerFault.

Eu DO quero excluir todos os arquivos N mais recentes em uma pasta específica.

Plano de fundo: um sistema remoto é configurado para despejar arquivos mortos periódicos em um compartilhamento em um servidor Windows. Esses arquivos têm uma convenção de nomes de YYYYMMDD-hhmm.ext. Caso o processo de arquivamento falhe, não quero que o script de exclusão exclua os arquivos apenas porque são mais antigos do que muitos dias. Não há como configurar o sistema remoto para limpar os arquivos como parte do processo de arquivamento.

Assim, por exemplo, quando o script é executado, pode haver 10 arquivos, pode haver 7 arquivos, pode haver 5 arquivos na pasta. Eu preciso sempre manter pelo menos os 5 mais recentes, independentemente de quantos anos eles tenham.

Isso pode ser feito com o PowerShell?

EDIT: seria desejável ignorar arquivos ou pastas que não correspondam à convenção de nomenclatura. Outros arquivos e pastas não devem ser excluídos, nem devem confundir o script (resultando na retenção de menos de 5 arquivos compactados).

    
por Jonathan J 25.07.2013 / 20:56

5 respostas

6

Uso: yourScript.ps1 -Path path \ to \ run \ em relação a [-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
}

Eu não espero que isso seja realmente melhor do que o de @ John, eu acabei de fazer isso para testar os parâmetros, regexp e não usar um loop. Fazer uma correspondência regex tem o benefício de excluir outros arquivos com .ext que não correspondam ao formato (por exemplo, 20130504-1200.txt.ext, 20.ext), mas é duvidoso que isso se aplique.

Fiquei chateado ao descobrir que se $ NumberToSave = $ items.Count, em seguida, a declaração if é necessária, caso contrário, não estaria lá. Tecnicamente:

$items[$numberToSave..$items.Count] | Remove-Item 

funciona bem (o PowerShell não parece errar se você faz referência aos limites da matriz, apenas os manipula e ignora), mas isso parecia potencialmente confuso.

    
por 26.07.2013 / 06:50
4
$n = x

$items = Get-ChildItem path_to_folder\*.ext

$items | 
  Sort-Object Name -Descending | 
  Select-Object -Last ($items.count - $n) | 
  Foreach-Object { Remove-Item $_ }
    
por 25.07.2013 / 21:35
0

Um amigo forneceu este script:

# 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
    }
}
    
por 31.07.2013 / 21:02
0
# 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
    
por 01.08.2013 / 22:07
-1

Já fiz isso no Bash antes e você pode traduzi-lo para o PowerShell. Pessoalmente, sou um administrador do Linux e não sei o suficiente sobre o Windows / PowerShell para fazer isso sozinho.

#!/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

Desculpe, não pude ser mais útil.

Edit: Eu também coloquei isso aqui no caso de um administrador do Linux precisar de informações semelhantes.

    
por 25.07.2013 / 21:02