Removendo arquivos com mais de 1 mês, mas deixe um arquivo por mês

3

Eu tento criar scripts semelhantes a Remover arquivos com mais de um mês, mas deixar os arquivos criados no primeiro dia do mês .
A diferença é que preciso de um arquivo por mês.

Estou usando o script com o meu ambiente de compilação, que não é executado diariamente, causado pela pesquisa scm.

Acho que a única maneira de conseguir isso é usar um find para obter todos os arquivos "antigos" e executar algumas verificações. Primeiro eu removia todos os arquivos da lista, que foi mantido como arquivo de mês. Então eu removia um arquivo como mês da lista e depois eu apagava todos os arquivos da lista.

Eu perdi uma funcionalidade de encontrar ou semelhante?

    
por CSchulz 16.07.2013 / 12:25

1 resposta

4

Resumo : A solução mais completa é a última, escolha aquela que melhor lhe convier, dependendo do que exatamente você deseja fazer.

Na verdade, se tudo o que você deseja é manter um arquivo por mês, basta renomear todos os arquivos month . Isso substituirá tudo, exceto um arquivo por mês. Você não deu informações sobre o tipo de arquivo ou onde esses arquivos estão. Estou assumindo que todos os arquivos estão no mesmo diretório e não há subdiretórios. Se isso estiver errado, atualize sua pergunta com mais detalhes e atualizarei minha resposta.

for file in *; do 
  month=$(date -d 'stat -c %y $file | cut -f 1 -d ' ' ' +%B);
  mv $file $month;
done 

O script acima deixará você com arquivos chamados January , February etc. Se você precisar manter os nomes dos arquivos originais, você pode tentar:

for file in *; do 
 month=$(date -d 'stat -c %y $file | cut -f 1 -d ' ' ' +%B); 
 rm *.$month; 
 mv $file $file.$month; 
done

Isso deixará você com arquivos chamados <FILENAME>.<MONTH> , por exemplo, foo.January .

Ambas as soluções acima são muito simplistas. Uma solução mais geral que também funcionará em arquivos em sub-diretórios e ignora arquivos com menos de um mês de idade é:

find . -type f -mtime +29 | while IFS= read -r file; do 
 month=$(date -d 'stat -c %y "$file" | cut -f 1 -d ' ' ' +%B); 
 find . -type f -name "*$month" -delete
 mv "$file" "$file.$month"; 
done

NOTAS:

  • A solução acima procurará arquivos com pelo menos um mês de idade no diretório atual e em todos os subdiretórios e manterá apenas um arquivo por mês. Isso significa que, se você tiver dois arquivos que foram modificados pela última vez em janeiro, um deles é ./foo e o outro baz/bar , apenas um será mantido, seja ./foo.January ou baz/bar.January .

  • Isso pressupõe que você não tenha arquivos do ano passado que possam ser denominados foo.January . Se você fizer isso, eles serão excluídos.

Por fim, um pouco mais complexo que permitirá que você mantenha os nomes dos arquivos inalterados e evite os problemas mencionados acima:

tmp='mktemp -u XXXX';
find . -type f -mtime +29 | while IFS= read -r file; do 
  date=$(date -d 'stat -c %y "$file" | cut -f 1 -d ' ' ' +%B%Y);
  foo=$tmp"_"$date; 
  find . -type f -name "*$foo" -delete
  mv "$file" "$file.$foo"; 
done
find . -type f -name "*$tmp*" | while IFS= read -r file; do 
  mv "$file" "${file%.*}";
done 

EXPLICAÇÃO:

Este script usa mktemp -u XXXX (por exemplo, Xy12 ) para gerar uma string aleatória que é então combinada com a data (por exemplo, January2008 ) do arquivo. Todos os arquivos com pelo menos um mês (> 29 dias, desculpe, fevereiro) são renomeados para filename.Xy12_January2008 . O segundo loop localiza todos os arquivos cujo nome contém a string aleatória ( Xy12 ) e remove sua extensão, portanto filename.Xy12_January2008 torna-se filename novamente.

O resultado final é um arquivo de cada mês de cada ano, com o nome do arquivo original inalterado. O script pode lidar com nomes de arquivos com espaços e encontrará arquivos no diretório atual e em todos os subdiretórios.

    
por 16.07.2013 / 13:28