Exclua arquivos em um diretório com mais de 7 dias, mas sempre deixe pelo menos 20 arquivos intactos

0

Iniciante aqui: Eu quero sincronizar fotos para uma pasta, mas quero que elas sejam recentes. É por isso que quero que sejam excluídos se tiverem mais de 7 dias.

Código atual:

find ./recentpicturesdirectory -mtime -7 -type f -delete 

Agora preciso de uma exceção porque sempre deve haver no mínimo 20 fotos na pasta.

Eu fiz algumas pesquisas, mas não consegui descobrir. Talvez use algo mais que o comando find?

Primeira tentativa triste (disse que sou iniciante)

SIZE=find recentpictesfolder -type f | wc -l

find ./recentpicturesdirectory -mtime -7 -type f \(-iname ".*" ! **if files part of -> .. i dont know ...**$SIZE ) -delete 
    
por Dominik Meyer 07.07.2017 / 20:06

3 respostas

1

Portanto, queremos obter os arquivos (regulares) que têm mtime há mais de 7 dias e NÃO estão nos 20 arquivos mais recentes.

Uma maneira de fazer isso é construir uma lista de arquivos junto com seus tempos de modificação e um sinalizador indicando se o arquivo é mtime +7 ou não. Podemos então ordenar a lista por mtime , e pegar todos menos os 20 mais recentes 1 . Por fim, repita a lista resultante e exclua somente aqueles que atendem ao limite de idade:

find ./recentpicturesdirectory -type f \( -mtime +7 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p
rm ./recentpicturesdirectory/**/*(.^om[1,20]^m+7)
' | sort -zk2,2 | head -zn -20 | while read -r -d '' flag _ file; do \ case "$flag" in 'Y') echo rm "$file" ;; *) echo "skipping $file (too new)" ;; esac done

Usando -z termination e adicionando o sort flag aos comandos head e tail (ou echo ), podemos manipular qualquer nome de arquivo legal sem nos sufocarmos no espaço em branco.

O head -n -20 é adicionado para fins de teste; remova-o assim que tiver certeza de que os arquivos desejados estão selecionados para exclusão .

1 Se classificarmos em ordem crescente de tempo (ou seja, antigo para novo), podemos usar tail -n +21 para selecionar todos, exceto os últimos 20; alternativamente, poderíamos classificar em ordem decrescente de mtime (novo para antigo) e usar zsh

Se você tem **/* , então você pode fazer tudo com qualificadores glob, eu acho:

print -rl ./recentpicturesdirectory/**/*(.^om[1,20]^m+7)

onde

  • globstar corresponde recursivamente (equivalente a bash (.) )
  • om[1,20] corresponde somente a arquivos regulares
  • m+7 lista os resultados em ordem crescente de tempo e seleciona os primeiros 20
  • mtime corresponde apenas a arquivos com ^ > 7 dias
  • regular files NOT (in 20 most recent by mtime OR NOT mtime +7 days) inverte tudo o que se segue

então a lógica é

regular files (NOT in 20 most recent by mtime) AND (mtime +7 days)

que (por aplicação das regras de Morgan) é equivalente a

%code%

Por favor, faça um teste primeiro, por exemplo,

find ./recentpicturesdirectory -type f \( -mtime +7 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p
rm ./recentpicturesdirectory/**/*(.^om[1,20]^m+7)
' | sort -zk2,2 | head -zn -20 | while read -r -d '' flag _ file; do \ case "$flag" in 'Y') echo rm "$file" ;; *) echo "skipping $file (too new)" ;; esac done
    
por steeldriver 08.07.2017 / 03:31
0

Aqui está um script simples para fazer isso:

#!/bin/bash

IMGSPATH="/path/to/somewhere"

# count of all files within your directory
count=$(find $IMGSPATH -type f | wc -l)

# remove the ones older than of 7 days
while [ "$count" -gt "20" ]
do 
 find $IMGSPATH -type f -mtime +7 -print -delete -quit
 count=$((--count))
done
  1. Primeiro, contamos todos os arquivos no diretório desejado.
  2. Embora o número de arquivos dentro desse diretório seja maior que "20", faça:
    • Encontre o primeiro arquivo mais antigo que "7" dias.
    • Remover
    • Diminuir a contagem de arquivos disponíveis
    • Faça "# 2" novamente ...

Para testar:

mkdir /tmp/lab
cd /lab
touch {1..40}
touch -d "10 days ago" {1..20}

Salve o script e execute-o para /tmp/lab agora, os arquivos de 1 a 20 devem ser excluídos, execute:

touch -d "10 days ago" {21..35}

execute o script novamente, nada será removido porque você não tem mais de 20 arquivos, seja ele velho ou não.

    
por Ravexina 07.07.2017 / 20:47
0

Minha abordagem subjacente é a mesma da resposta da steeldriver , mas vou mantê-la um pouco mais simples. Os comandos a seguir imprimirão uma lista de arquivos em recentpicturesdirectory omitindo o retain_count (20) mais novo e todos os menores que retain_younger_days dias (7).

find recentpicturesdirectory -type f -printf '%T@ %p
xargs -r0 -- rm --
' | sort --zero-terminated --reverse --numeric-sort --field-separator=' ' --key 1,1 | gawk -F ' ' -v RS='
find recentpicturesdirectory -type f -printf '%T@ %p
xargs -r0 -- rm --
' | sort --zero-terminated --reverse --numeric-sort --field-separator=' ' --key 1,1 | gawk -F ' ' -v RS='%pre%' -v ORS='%pre%' -v retain_count=20 -v retain_younger_days=7 \ 'BEGIN{ maxage = systime() - retain_younger_days * 24 * 3600; } (NR > retain_count) && (int($1) < maxage) { print(substr($0, length($1) + 2)); }'
' -v ORS='%pre%' -v retain_count=20 -v retain_younger_days=7 \ 'BEGIN{ maxage = systime() - retain_younger_days * 24 * 3600; } (NR > retain_count) && (int($1) < maxage) { print(substr($0, length($1) + 2)); }'

Como a saída é terminada por caractere nulo, talvez você queira direcioná-la por tr 'find recentpicturesdirectory -type f -printf '%T@ %precentpicturesdirectory'' '\n' para exibi-la em termos humanos.

Explicação

  • -type -f

    Selecione as entradas (aninhadas) de -printf '%T@ %psort --zero-terminated --reverse --numeric-sort --field-separator=' ' --key 1,1' que são arquivos regulares ( -z ) e imprima a hora da última modificação e o caminho terminado pelo caractere nulo ( --zero-terminated ).

  • -k

    Classifique os registros terminados pelo caractere nulo ( --key 1,1 / -t ) com base no primeiro campo ( --field-separator=' ' / -n ) com o separador de campo de caractere de espaço ( --numeric-sort / -r ) interpretado como números decimais ( --reverse / gawk -F ' ' -v RS='-F ' '' -v ORS='-v RS='retain_count' -v ORS='retain_younger_days'' -v retain_count=20 -v retain_younger_days=7 ) em ordem decrescente ( BEGIN{ maxage = systime() - retain_younger_days * 24 * 3600; } / maxage ).

  • retain_younger_days

    Execute um programa GNU AWK com o separador de campo de caractere de espaço ( (NR > retain_count) && (int($1) < maxage) ), o separador de registro de entrada e saída de caractere nulo ( retain_count ) e as variáveis maxage e print(substr($0, length($1) + 2)) definidas como 20 e 7 respectivamente.

  • %code%

    No início do programa, defina %code% como o tempo atual do sistema, em segundos, menos o valor de %code% convertido de dias para segundos.

  • %code%

    Selecione números de registro acima de %code% e um valor na primeira coluna abaixo de %code% .

  • %code%

    Imprime o registro atual omitindo o primeiro campo e o separador de campo subsequente, i. e. o nome do caminho após a hora da modificação.

Como remover os arquivos impressos

Se você confirmou que deseja remover os arquivos listados, pode enviar a lista para:

%pre%     
por David Foerster 18.07.2017 / 10:18