Escrevendo somente arquivos existentes em um diretório ou outro ou tendo tamanho ou hora do último modificado

1

Estou escrevendo um script no qual preciso comparar dois diretórios (recursivamente) e gravar somente arquivos se eles tiverem tamanho ou hora de modificação diferentes (AA-MM-DD HH: MM) ou se o arquivo existir apenas em um diretório .

A saída deve estar no formato:

<dir1>:<local-path> <size> <last-modify> <dir2>:<local-path> <size> <last-modify>

Se o arquivo existir apenas em um diretório:

<dir1>:<local-path> <size> <last-modify>

ou

<dir2>:<local-path> <size> <last-modify>

Até agora consegui obter meus dados no formato especificado usando:

find dir1 -type f -exec stat -c '%n %s %y' {} \; | sed 's,^[^/]*/,,' | sed 's/\:[^:]*$//' | sort # > dir1.txt
find dir2 -type f -exec stat -c '%n %s %y' {} \; | sed 's,^[^/]*/,,' | sed 's/\:[^:]*$//' | sort # > dir2.txt

O que me dá duas listas ordenadas de arquivos em determinados diretórios e subdiretórios e seu tamanho e o último registro de data e hora modificado.

Agora, preciso compará-los de alguma forma e colocá-los no formato especificado acima. Eu tentei usar diff -y mas compara linha por linha, mas eu preciso do mesmo nome para o mesmo nome. Eu também tentei comunicação, mas não sei como transformar esse formato de saída.

Alguma ideia?

    
por Saintan 18.11.2016 / 16:08

2 respostas

1

Acho que tentaria colocar algo em conjunto usando o rsync no modo dry-run ( --dry-run ou -n ).

Para ilustrar, dado:

$ tree -Ds Adir/ Bdir/
Adir/
├── [       4096 Nov 19  9:36]  sub1
│   ├── [         35 Nov 19  9:35]  common
│   └── [         23 Nov 19  9:36]  onlyA
├── [       4096 Nov 19  9:41]  sub2
│   ├── [         35 Nov 19  9:35]  common
│   ├── [         44 Nov 19  9:44]  newerA
│   ├── [         44 Nov 19  9:37]  olderA
│   └── [          6 Nov 19 10:36]  size
└── [       4096 Nov 19  9:35]  sub3
    └── [         35 Nov 19  9:35]  common
Bdir/
├── [       4096 Nov 19  9:46]  sub1
│   └── [         35 Nov 19  9:35]  common
├── [       4096 Nov 19 10:36]  sub2
│   ├── [         35 Nov 19  9:35]  common
│   ├── [         44 Nov 19  9:38]  newerA
│   ├── [         44 Nov 19  9:44]  olderA
│   └── [         24 Nov 19 10:36]  size
└── [       4096 Nov 19  9:40]  sub3
    ├── [         35 Nov 19  9:35]  common
    └── [         23 Nov 19  9:40]  onlyB

6 directories, 14 files

podemos listar arquivos com tamanhos ou tempos de modificação diferentes da seguinte forma:

$ rsync -aOn --delete --itemize-changes Adir/ Bdir/
*deleting   sub3/onlyB
>f+++++++++ sub1/onlyA
>f..t...... sub2/newerA
>f..t...... sub2/olderA
>f.s....... sub2/size

[A string de mudança não importa realmente para nossos propósitos, mas por exemplo *deleting indica que sub3/onlyB não está presente no diretório de origem; s indica uma diferença de tamanho; t indica uma diferença no tempo de modificação.]

Infelizmente, não parece ser possível obter os timestamps reais diretamente da saída rsync, mas podemos simplesmente ler a lista de arquivos e declarar os arquivos correspondentes em cada diretório:

#!/bin/bash

dirA="$1"
dirB="$2"

rsync -aOn --itemize-changes --delete "$dirA"/ "$dirB"/ | while read -r c f ; do
  printf '%s:%s  ' "$dirA" "$(cd "$dirA" && stat -c '%n %s %y' "$f" 2>/dev/null || printf '(none) - - - -')"
  printf '%s:%s\n' "$dirB" "$(cd "$dirB" && stat -c '%n %s %y' "$f" 2>/dev/null || printf '(none) - - - -')"
done

que podemos usar da seguinte forma

$ ./rstat.sh Adir Bdir | column -t
Adir:(none)       -   -           -                   -      Bdir:sub3/onlyB   23  2016-11-19  09:40:12.253318393  -0500
Adir:sub1/onlyA   23  2016-11-19  09:36:52.220421434  -0500  Bdir:(none)       -   -           -                   -
Adir:sub2/newerA  44  2016-11-19  09:44:45.953236221  -0500  Bdir:sub2/newerA  44  2016-11-19  09:38:33.270838033  -0500
Adir:sub2/olderA  44  2016-11-19  09:37:41.675642039  -0500  Bdir:sub2/olderA  44  2016-11-19  09:44:45.953236221  -0500
Adir:sub2/size    6   2016-11-19  10:36:31.460487036  -0500  Bdir:sub2/size    24  2016-11-19  10:36:31.460487036  -0500
    
por steeldriver 18.11.2016 / 17:19
0

Acho que você já acabou, aqui está abaixo para:

Se o arquivo existir apenas no diretório1 (considerando quaisquer diferenças em nome, tamanho ou tempo de modificação:

grep -Fxvf dir2.txt dir1.txt > inDir1Only

Ou se o arquivo existir apenas no diretório2:

grep -Fxvf dir1.txt dir2.txt > inDir2Only

Então, no final da sua pergunta "escreva somente arquivos se eles tiverem tamanho ou tempo de modificação diferentes (AA-MM-DD HH: MM)", apenas concatene dois resultados acima, como segue:)

assumindo que o conteúdo inDir1Only e inDir2Only seja o seguinte:

$ cat inDir1Only
    c.txt 26 2016-11-04 14:23
    b.txt 26 2016-11-04 14:23
$ cat inDir2Only
    b.txt 57 2016-11-04 18:20
    a.txt 14 2016-11-04 18:11

desde sua saída desejada seria como abaixo abaixo após a execução abaixo do comando awk ,

$ awk 'NR==FNR{seen[$1]=$0;next} {
    print "inDir1Only:"$0, ($1 in seen) ?"inDir2Only:"seen[$1]:"";seen[$1]=""}
END{
    for(x in seen) if (seen[x]!=NULL) print "inDir2Only:"seen[x]
}' inDir2Only inDir1Only

inDir1Only:c.txt 26 2016-11-04 14:23 
inDir1Only:b.txt 26 2016-11-04 14:23 inDir2Only:b.txt 57 2016-11-04 18:20
inDir2Only:a.txt 14 2016-11-04 18:11
    
por sddgob 18.11.2016 / 16:30