verificar se todos os arquivos de uma pasta também estão em outra pasta

6

Eu basicamente tenho um diretório a com muitas imagens. Agora quero verificar se todas essas imagens estão no diretório b . O ponto é que muitas imagens em b não estão diretamente em b , mas em subdiretórios.

Além disso, não quero depender de nomes de arquivos, mas de conteúdo de arquivos.

(por causa da tag bash: prefiro uma resposta bash, mas se for alguma outra linguagem ou se estiver usando outro programa, tudo bem também)

    
por Uroc327 10.12.2014 / 14:49

3 respostas

3

Como você deseja compará-los por conteúdo, o uso de hashes parece ser uma maneira de fazer isso.

Você pode usar o comando find para obter uma lista de caminhos de arquivo de um diretório. A opção -type f deixará de fora todos os diretórios e apenas os caminhos de saída para arquivos regulares. A opção -exec md5sum {} \; pegará os caminhos encontrados e os dará ao comando md5sum para transformar em uma lista md5 hash + seus caminhos de arquivo ('md5_hash / path / to / file').

Enviamos essa lista para o comando cut . A primeira opção -f 1 diz para apenas pegar a primeira coluna (os hashes). O segundo -d ' ' diz para usar um caractere de espaço como o delimitador entre as colunas. O padrão é uma TAB.

Enviamos essa lista de hashes para o comando sort, para facilitar para diff .

O operador <( command ) é chamado de Substituição de processo . Ele pega a saída de um comando e o transforma em um pseudo arquivo para comandos que os exigem como entrada (para uma explicação menos simples, siga o link). Dessa forma, parece diff como se quiséssemos comparar dois arquivos.

:~$ diff <(find folder1/ -type f -exec md5sum {} \; | cut -f 1 -d ' ' | sort) \
    <(find folder2/ -type f -exec md5sum {} \; | cut -f 1 -d ' ' | sort)

Nota: não se esqueça de substituir folder1 / e folder2 / por suas pastas atuais.

Isso lhe dará uma lista de hashes md5 dos arquivos que estão apenas em um ou no outro.

Se você quiser saber quais arquivos estão realmente ausentes, faça o seguinte:

:~$ find folder1/ -type f -exec md5sum {} \; | sort | grep my_md5_hash

Se você tiver muitos arquivos para verificar, seria prudente salvar os resultados dos dois comandos <(find ...) e compará-los como:

:~$ diff list1.txt list2.txt
:~$ cat list1.txt | grep my_md5_hash
    
por 10.12.2014 / 15:28
0

Veja a resposta para uma pergunta semelhante de duas semanas atrás.

find . -type f -exec md5sum {} + | sort | sed 's/  */!/1' | awk -F\| 'BEGIN{first=1}{if($1==lastid){if(first){first=0;print lastid, lastfile}print$1, $2} else first=1; lastid=$1;lastfile=$2}'
    
por 10.12.2014 / 15:54
0

Supondo que todos sejam arquivos * .jpg, faça um:

Para encontrar os arquivos presentes:

grep -Ff <(for i in </path/to/directory/a>/*.jpg ; do md5sum $i | awk {'print $1'}; done) <(find </path/to/directoryb/ -iname "*.jpg" | xargs md5sum)

O loop for aqui cria uma lista de somas de verificação md5 de todos os arquivos *.jpg no diretório 'a' e o find aqui criará uma lista de somas de verificação md5 de todos os arquivos *.jpg no diretório ' b '(incluindo sudirectories).

O grep -fF comparará essas duas listas e o comando completo produzirá uma saída de 2 colunas com a 1ª columm sendo a soma de verificação md5 dos arquivos que estão presentes e a 2ª coluna sendo o nome do arquivo (com caminho completo) do arquivo. arquivos que correspondem no diretório 'b'. Você pode usar um | awk {'print $2'} adicional se quiser obter apenas os nomes de arquivo.

Para encontrar os arquivos que não estão presentes:

grep -vFf <(for i in </path/to/directory/a>/*.jpg ; do md5sum $i | awk {'print $1'}; done) <(find </path/to/directoryb/ -iname "*.jpg" | xargs md5sum )

Faz o mesmo que o primeiro comando grep, mas usa a opção -v para listar apenas o que não combina.

O que você está procurando:

Se todos os arquivos no diretório 'a' estiverem presentes, o segundo grep não deve retornar nenhuma saída.

Substitua * .jpg por qualquer extensão que você queira pesquisar.

Da página man de grep :

   -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  The empty file contains zero patterns, and therefore matches nothing.
          (-f is specified by POSIX.)

    -F, --fixed-strings
          Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to  be  matched.   (-F  is
          specified by POSIX.)

-v, --invert-match
              Invert the sense of matching, to select non-matching lines. 
    
por 10.12.2014 / 18:46