Como iterar arquivos e deletar aqueles com mais de x dias, mas NÃO em uso

2

Então, eu consegui descobrir partes disso, mas estou tendo problemas para juntá-las. Eu tenho uma tarefa que eu preciso para automatizar - eu tenho pastas cheias de gigabytes de arquivos obsoletos, e eu quero limpá-los se eles atenderem a dois critérios.

  1. Os arquivos não devem ter sido modificados nos últimos 14 dias - para isso, estou usando o find -

find /dir/* -type f -mtime +14

  1. E os arquivos não podem estar em uso, o que pode ser determinado por

lsof /dir/*

Eu não sei bash bastante bem ainda para descobrir como combinar esses comandos. Ajuda seria apreciada. Eu acho que essencialmente quero percorrer cada linha de saída do find, verificar se ela está presente na saída do lsof, e se não, rm -f - no entanto, estou aberto a metodologias alternativas se elas atingirem o objetivo!

    
por tastyCIDR 14.11.2015 / 03:51

3 respostas

1

Os seguintes itens devem funcionar:

for x in 'find <dir> -type f -mtime +14'; do lsof "$x" >/dev/null && echo "$x in use" || echo "$x not in use" ; done

Em vez do comando echo "$x not in use" , você pode colocar seu comando rm "$x" .

Como funciona:

  • localizar arquivos, modificados pela última vez há 14 dias:

find <dir> -type f -mtime +14

  • faça um loop sobre itens em uma lista:

for x in <list>; do <command>; done

  • execute o comando 2 se o resultado de lsof for 0 , senão execute o comando 1:

lsof "$x" && <command 1> || <command 2>

Isso depende da avaliação lenta do Bash para executar o comando 1 ou o comando 2.

No meu sistema (Ubuntu 14.04) isso funciona com nomes de arquivo com espaços neles e até mesmo para nomes de arquivos com ? e * neles.
No entanto, isso não garante que ele funcionará com todos os shell de qualquer sistema. Por favor, teste antes de substituir o comando echo pelo comando rm .

    
por 14.11.2015 / 04:43
2

Use a ação -exec em find para executar um comando para cada arquivo. Isso executa um programa com argumentos; se você precisar de um comando mais complexo (com expansão de variáveis, condicionais, etc.), então você precisa invocar um shell explicitamente:

find /dir/* -type f -mtime +14 -exec sh -c '
  if …; then
    rm "$0"
  fi
' {} \;

Para testar se um arquivo está aberto no momento, a maneira mais direta é chamar fuser .

find /dir/* -type f -mtime +14 -exec sh -c '
  if ! fuser "$0" >/dev/null 2>/dev/null; then
    rm "$0"
  fi
' {} \;

Tenha em atenção que só porque um ficheiro não foi modificado há muito tempo e não está aberto no momento não significa que não seja útil. Eu recomendo pelo menos testar que o arquivo não foi lido há algum tempo; isso pode ser testado com o tempo de acesso, mas cuidado com os sistemas Linux que não atualizam o tempo de acesso de maneira confiável. (Independentemente de como eles são e com que frequência depende da versão do kernel, das opções de montagem e de como o tempo de acesso se compara à hora da modificação).

Eu recomendo rever os arquivos antes de excluí-los.

find /dir/* -type f -mtime +14 -atime +14 -exec sh -c '
  if ! fuser "$0" >/dev/null 2>/dev/null; then
    echo "$0"
  fi
' {} \; >files-to-delete-potentially.txt

Revise os nomes dos arquivos e apague os que você deseja manter. Então, para removê-los todos, assumindo que nenhum dos nomes de arquivo contém um caractere de nova linha, você pode usar

<files-to-delete-potentially.txt tr '\n' '
find /dir/* -type f -mtime +14 -exec sh -c '
  if …; then
    rm "$0"
  fi
' {} \;
' | xargs -0 rm
    
por 15.11.2015 / 01:35
1

Em vez de usar lsof , que tem um pesadelo emaranhado de opções e uma saída interessante para analisar, sugiro usar as opções -atime ou -amin para find . Estes permitem especificar o tempo de acesso ao arquivo em dias ou segundos, respectivamente.

Em vez de usar outro processo para descobrir se um arquivo está "em uso" no momento, é possível verificar se ele foi acessado nos últimos N segundos ou dias.

O comando a seguir lista todos os arquivos que foram modificados há mais de 14 dias e acessados há menos de 60 segundos.

find "$dir" -type f -mtime +14 -amin -60

Para remover os arquivos que correspondem a esse critério, você pode usar o comando find ' -exec command ; '. O mais estranho disso é que você especifica cada argumento de comando separadamente para localizar e finalizar com um ponto-e-vírgula ( ; ). Se {} aparecer em qualquer argumento, ele será substituído pelo nome do nome do arquivo que está sendo processado.

Este comando remove todos os arquivos criados há mais de 14 dias e não é acessado nos últimos 60 minutos:

find "$dir" -type f -mtime +14 -amin -60 -exec rm '{}' \;
    
por 14.11.2015 / 05:44

Tags