Arquivar arquivos por mês

4

TAREFA

Eu preciso escrever um script bash que arquivaria arquivos por mês. Ou seja, os arquivos com datas de modificação de 2016-12 seriam compactados no arquivo 2016-12_archive.tar.gz e os arquivos com datas de modificação de 2017-01 seriam empacotados em 2017-01_archive.tar.gz archive, etc.

Exemplo:

FILE NAME   MODIFICATION DATE
file1.log       2016-12-30       ----> 2016-12_archive.tar.gz
file2.log       2016-12-31       ----> 2016-12_archive.tar.gz
file3.log       2017-01-01       ----> 2017-01_archive.tar.gz
file4.log       2017-01-02       ----> 2017-01_archive.tar.gz
file5.log       2017-01-15       ----> 2017-01_archive.tar.gz

Minhas dificuldades

Os principais problemas que tenho:

  1. Como obter a data de modificação do arquivo via bash?

  2. Como processar todos os arquivos em um determinado diretório (para que eles tenham sido arquivados em um arquivo apropriado)?

Minhas tentativas de resolver os problemas

  1. Encontrei duas maneiras de descobrir a data de modificação do arquivo: date -r $ file +% F e find dir -name filename -printf '% TY-% Tm-% Td \ n' . Ambos não funcionam no computador (OS AIX, eu não sou uma raiz). Também não consigo ver o comando 'ls -lc' (não parece haver data de modificação).

  2. Eu tenho apenas uma ideia: obter todas as datas do arquivo de modificação no formato YYYY-MM e, em seguida, criar uma lista de seus valores exclusivos. Então, para cada item desta lista, encontre todos os arquivos com data de modificação apropriada.

Tentativas consolidadas

Usando istat para obter a data de modificação:

$ istat filename
Inode 86741 on device 10/8 File
Protection: rw-r-----
Owner: 6361(user2) Group: 621(norgroup)
Link count: 1 Length 116 bytes

Last updated: 16 февраля 2017 г., 14:25:11 MSK
Last modified: 16 февраля 2017 г., 14:25:11 MSK
Last accessed: 16 февраля 2017 г., 16:08:46 MSK

É assim que posso obter o valor da Última modificação para cada arquivo:

for logFile in *.log; do
   mdfDate=$(istat $logFile | grep "Last modified");
   echo $logFile $mdfDate
done

Saída:

file1.log Last modified: 30 декабря 2016 г., 14:25:11 MSK
file2.log Last modified: 31 декабря 2016 г., 14:26:11 MSK
file3.log Last modified: 01 января 2017 г., 14:27:11 MSK
file4.log Last modified: 02 января 2017 г., 14:28:11 MSK
file5.log Last modified: 15 января 2017 г., 14:29:11 MSK

O próximo passo é extrair data no formato unix.

Por algum motivo, cut não funciona corretamente. Awk é muito pesado e sofisticado. Talvez sed ?

    
por Vikora 16.02.2017 / 21:50

1 resposta

3

Se você tivesse acesso ao GNU date , isso seria muito mais fácil. Como é, seria mais simples usar uma linguagem mais sofisticada. Por exemplo, Perl:

#!/usr/bin/perl -w
use strict;
use POSIX qw(strftime);

my $targetDir = $ARGV[0] || ".";
my %tarFiles;
open(my $input, '-|', "find \"$targetDir\" -type f -name '*.log'");
while (<$input>) {
    # remove trailing newlines
    chomp;
    ## Get the file name
    my $file = $_;
    # Open it as a file handle for stat()
    open(my $fh, '<', "$file") or die;
    # Get the file's stats
    my @stats = stat($fh);
    close($fh);
    # modification time
    my $mtime = $stats[9];
    # Convert to YYYY-MM and build the tar file name
    my $tarfile = strftime "%Y-%m_archive.tar.gz", localtime($mtime);
    # Add to the list of files for this tar file
    push @{$tarFiles{$tarfile}}, qq("$file");
}

for my $tarFile (keys(%tarFiles)) {
    # Build the command that creates the tar file
    my $tarCom = "tar cvzf $tarFile @{$tarFiles{$tarFile}}";
    print "COMMAND: $tarCom\n";

    # Uncomment this line to run the command
    # system("$tarCom")
}                           

Salve o script como makeTars.pl (ou o que quiser) em algum lugar no seu $PATH , torne-o executável ( chmod +x /path/to/makeTars.pl ) e execute assim:

makeTars.pl /path/to/target/dir

Por exemplo:

$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Dec 30 00:00  file1.log
-rw-r--r-- 1 terdon terdon 0 Dec 31 00:00  file2.log
-rw-r--r-- 1 terdon terdon 0 Jan  1  2016  file3.log
-rw-r--r-- 1 terdon terdon 0 Jan  2  2016  file4.log
-rw-r--r-- 1 terdon terdon 0 Jan  3  2016  file5.log
-rw-r--r-- 1 terdon terdon 0 Jan  3  2016 'file5 with spaces.log'
$ makeTars.pl .
COMMAND: tar cvzf 2017-02_archive.tar.gz "."
COMMAND: tar cvzf 2016-12_archive.tar.gz "./file2.log" "./file1.log"
COMMAND: tar cvzf 2016-01_archive.tar.gz "./file5 with spaces.log" "./file5.log" "./file4.log" "./file3.log"

Quando estiver satisfeito com o que você deseja, descomente a última linha ( system("$tarCom") ) para criar os arquivos tar.

Observe que isso será interrompido se os nomes dos arquivos contiverem novas linhas, mas espero que isso não seja um problema com os arquivos de log.

    
por 21.02.2017 / 01:25

Tags