Como manter exatamente um arquivo em um diretório?

3

Eu recuperei arquivos e atualmente eles têm essa estrutura:

root/MD5_of_file1/file1
root/MD5_of_file2/file2
...
root/MD5_of_filen/filen

Obviamente, as duplicatas estão agora na mesma pasta. O nome do arquivo não contém informações, apenas o número do bloco em que foi encontrado durante a recuperação.

Eu quero nivelar a estrutura, mantendo apenas um arquivo para cada MD5. Como eu poderia fazer isso com eficiência?

Só para ficar claro, aqui estão alguns dados reais:

feceee0fc150d191c5fd48ca6acee2f6
feceee0fc150d191c5fd48ca6acee2f6/f225407559.odt
feceee0fc150d191c5fd48ca6acee2f6/f94654911.odt
e905bb0a76c0055a2be1b8285d39c715
e905bb0a76c0055a2be1b8285d39c715/f0702423.odt
e905bb0a76c0055a2be1b8285d39c715/f26479232.odt
e905bb0a76c0055a2be1b8285d39c715/f3084695.odt

Eu quero achatar para algo assim:

f225407559.odt
f0702423.odt

mas não há garantias de que os nomes dos arquivos sejam distintos. Os arquivos podem ser facilmente renomeados para o MD5 correspondente de seu conteúdo, que já está computado, já que é o nome da pasta em que eles estão atualmente.

    
por alecail 12.11.2015 / 17:06

2 respostas

3

for i in *(/); do  mv $i/*([1]) $i.odt;  rm -rf $i; done

Ele está usando zsh qualifier: glob*([1]) seleciona o primeiro arquivo em ordem alfanumérica

    
por 12.11.2015 / 18:11
0

Em dois passos:

perl-rename 's;/([^/]*)/[^/]*$;/_file;' foo/**/*
rmdir foo/**/

Exemplo:

$ tree foo
foo
├── e905bb0a76c0055a2be1b8285d39c715
│   ├── f0702423.odt
│   ├── f26479232.odt
│   └── f3084695.odt
└── feceee0fc150d191c5fd48ca6acee2f6
    ├── f225407559.odt
    └── f94654911.odt

2 directories, 5 files
$ perl-rename -n 's;/([^/]*)/[^/]*$;/_file;' foo/**/*
foo/e905bb0a76c0055a2be1b8285d39c715/f0702423.odt -> foo/e905bb0a76c0055a2be1b8285d39c715_file
foo/e905bb0a76c0055a2be1b8285d39c715/f26479232.odt -> foo/e905bb0a76c0055a2be1b8285d39c715_file
foo/e905bb0a76c0055a2be1b8285d39c715/f3084695.odt -> foo/e905bb0a76c0055a2be1b8285d39c715_file
foo/feceee0fc150d191c5fd48ca6acee2f6/f225407559.odt -> foo/feceee0fc150d191c5fd48ca6acee2f6_file
foo/feceee0fc150d191c5fd48ca6acee2f6/f94654911.odt -> foo/feceee0fc150d191c5fd48ca6acee2f6_file
$ perl-rename 's;/([^/]*)/[^/]*$;/_file;' foo/**/*   
$ rmdir foo/**/
rmdir: failed to remove ‘foo/’: Directory not empty
$ tree foo
foo
├── e905bb0a76c0055a2be1b8285d39c715_file
└── feceee0fc150d191c5fd48ca6acee2f6_file

0 directories, 2 files

Outra forma de usar find , sort e awk :

find foo -type f | 
  sort -k2,2 -u -t/ |
  awk -F/ -v OFS=/ '{path=$0; file=$NF; NF--; cmd = "cp " path " " $0 "_" file;  ; system(cmd); system("rm -r "$0)}'

Exemplo:

$ find foo -type f | sort -k2,2 -u -t/ | awk -F/ -v OFS=/ '{path=$0; file=$NF; NF--; cmd = "cp " path " " $0 "_" file;  ; print cmd; print "rm -r "$0}'      
cp foo/e905bb0a76c0055a2be1b8285d39c715/f3084695.odt foo/e905bb0a76c0055a2be1b8285d39c715_f3084695.odt
rm -r foo/e905bb0a76c0055a2be1b8285d39c715
cp foo/feceee0fc150d191c5fd48ca6acee2f6/f225407559.odt foo/feceee0fc150d191c5fd48ca6acee2f6_f225407559.odt
rm -r foo/feceee0fc150d191c5fd48ca6acee2f6
$ find foo -type f | sort -k2,2 -u -t/ | awk -F/ -v OFS=/ '{path=$0; file=$NF; NF--; cmd = "cp " path " " $0 "_" file;  ; system(cmd); system("rm -r "$0)}'  
$ tree foo
foo
├── e905bb0a76c0055a2be1b8285d39c715_f3084695.odt
└── feceee0fc150d191c5fd48ca6acee2f6_f225407559.odt

0 directories, 2 files
    
por 12.11.2015 / 17:13