我已经恢复了文件,目前它们具有以下结构:
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
它使用zsh
glob 限定符:*([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