将命名错误的文件从一个深层嵌套的目录中复制到另一个扁平化的子目录,在 Bash 一行中?

Copy badly-named files from one deeply-nested dir, content-address rename them, to another flattened sub-directory, in a Bash one-liner?

如何将分布在一个深层嵌套子目录中的文件复制到另一个根本没有嵌套(即扁平的)的子目录?为了提高难度,我有这些 constraints/wrinkles.

  1. 虽然源文件具有相同的扩展名 (*.xlsx),但文件名中有空格。
  2. source 子目录及其所有内容都是只读的。
  3. 因为潜在的名称冲突,因为糟糕的文件名,因为我有一堆这些文件,它们的原始名称对我来说毫无用处,我想以某种方式对它们进行内容寻址.
  4. 脚本环境是Bash。
  5. 由于其他限制,在一行中执行此操作很重要。
  6. 为简单起见加分,越深奥同事越不容易理解

我试过 cpfindxargsparalleluuidgenmd5sum、Bash for 循环及其各种组合,但收效甚微。我能做到的最好的是为每个文件生成一个 random UUID。没关系,我想,但这并不是我想要的“内容寻址”,因为我想根据文件的 content.[=21 删除重复数据=]

供参考,看起来像这样,其中 sourcedest 是源和目标子目录。

find source/* -type f -exec sh -c 'for f; do cp "$f" 'dest'/"$(uuidgen)"; done' Renamer {} +

尽管 UUID 很不错,但我并没有特别关注它们,并且对其他想法持开放态度,以上述限制为模数。

谢谢!

使用命令md5sum计算文件内容的md5sum:

find * -type f -exec sh -c 'for f; do cp "$f" 'dest'/$(md5sum "$f" | sed -e s/[[:space:]].*//); done' _ {} +

这使用 sed 来修改 md5sum 的输出,使其不包含文件名而不是通常的 md5sum <file> | awk' {print }',这样我就不必考虑转义引号了。

当然,您可能会与 md5 发生哈希冲突,但您可以轻松地将哈希切换为使用 sha256sum 或任何您喜欢的方式。

如果使用 GNU Parallel,umläute 的解决方案会更短一些:

find * -type f -print0 | parallel -0 cp {} dest/'$(md5sum {} | sed -e s/[[:space:]].*//)'

已在包含多个连续空格和换行符的文件名上进行测试。