디렉토리에 하나의 파일만 보관하는 방법은 무엇입니까?

디렉토리에 하나의 파일만 보관하는 방법은 무엇입니까?

파일을 복원했는데 현재 파일 구조는 다음과 같습니다.

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

이제 중복 항목이 동일한 폴더에 있는 것 같습니다. 파일 이름에는 정보가 포함되지 않으며 복구 중에 발견된 블록 번호만 포함됩니다.

구조를 평면화하고 MD5당 하나의 파일만 유지하고 싶습니다. 이 작업을 어떻게 효율적으로 수행할 수 있습니까?

명확성을 위해 실제 데이터는 다음과 같습니다.

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

나는 다음과 같이 평면화하고 싶습니다.

f225407559.odt
f0702423.odt

그러나 파일 이름이 다르다는 보장은 없습니다. 파일은 현재 파일이 있는 폴더의 이름이므로 해당 내용의 MD5(계산된)로 쉽게 이름을 바꿀 수 있습니다.

답변1

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

zshglob 한정자를 사용합니다 . *([1])영숫자 순서로 첫 번째 파일을 선택합니다.

답변2

두 단계로:

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

예:

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

2 directories, 5 files
$ perl-rename -n 's;/([^/]*)/[^/]*$;/\1_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;/([^/]*)/[^/]*$;/\1_file;' foo/**/*   
$ rmdir foo/**/
rmdir: failed to remove ‘foo/’: Directory not empty
$ tree foo
foo
├── e905bb0a76c0055a2be1b8285d39c715_file
└── feceee0fc150d191c5fd48ca6acee2f6_file

0 directories, 2 files

find또 다른 방법은 , sort및 다음을 사용하는 것입니다 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)}'

예:

$ 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

관련 정보