从各个文件夹中获取所有文件并使用唯一名称复制它们

5

目前我正在使用这个命令从我的电视文件夹中获取所有的“fanart”,并将其转储到一个单独的文件夹中。

find /volume1/tv/ -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec cp {} /volume1/tv/_FANART \;

问题如下:很多这些文件的名称都相同,并且不能全部放在同一个文件夹中。例如:

  • 文件夹 A
    • fanart.jpg
  • 文件夹 B
    • fanart.jpg

有没有一种方法可以从各自的文件夹中复制这些文件并在目标文件夹中给它们一个唯一的名称?名称不需要描述性,随机名称也可以。

谢谢!


你希望它们如何保持唯一性?在名称冲突的情况下应该发生什么? - Willem Van Onsem
1
你为什么使用\(括号? - Willem Van Onsem
没有必要使用(括号 - 我是根据另一个命令进行操作的,那个命令恰好有这些。如果出现名称冲突,我希望它会添加后缀、生成随机字符字符串或其他任何方式。文件名并不重要,只要我能将它们全部合并到单个文件夹中即可。但由于这些命名冲突,我现在无法做到这一点。 - Big Millz
1
将MD5哈希附加到每个文件。这能解决你的问题吗? - UltraInstinct
1
添加一个MD5会很完美。我该怎么做呢? - Big Millz
3个回答

2
find /volume1/tv/ -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec cp --backup=numbered  {} /volume1/tv/_FANART \;

..

cp --backup=numbered  {}

如果文件已存在,则不会覆盖原文件,而是创建一个带有编号的备份文件。

这些文件将被隐藏。Ctrl+H 可以查看隐藏文件。


2
然而,这会将内容附加到文件名的末尾 - 使用后缀作为其内容提示的程序将有额外的数据需要过滤掉。 - Thomas Dickey

2
如果你想使用md5sum作为新的名称:
find /volume1/tv/ -type d -path '/volume1/tv/_FANART' -prune -o -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec sh -c 'md5=$(md5sum < "$0") && md5=${md5%% *}.jpg && echo cp "$0" "/volume1/tv/_FANART/$md5"' {} \;

每件事情都发生在sh命令中(所有命令都由&&分隔,但为了清晰起见,我省略了&&)。
md5=$(md5sum < "$0")
md5=${md5%% *}.jpg
cp "$0" "/volume1/tv/_FANART/$md5"'

$0 会被扩展为处理的文件名。我们首先计算文件的md5sum,然后只保留md5sum(md5sum将哈希值旁边放置连字符),并在其后添加.jpg,最后我们使用计算出的名称将文件复制到目标文件夹中。

注意事项。

  • I added

    -type d -path '/volume1/tv/_FANART` -prune -o
    

    to your command to omit this folder, since you very likely don't want to process it; it would actually be weird to process it, as its content is changed throughout find's traversal.

  • I left an echo in the command, so that absolutely nothing is copied (as is, it's 100% safe, you can just copy and paste it in your terminal): it only shows what commands are going to be performed (and you'll also see how fast/slow it is).
  • The command is 100% safe regarding funny filenames with spaces, newlines, globs, etc.
  • I used md5sum < fileand not md5sum file, because if the filename file contains special characters (like backslashes, newlines, etc.), md5sum (at least my version) prepends the hash with a backslash. Weird. By not giving a filename, we're safe, this won't happen.

1
您可以根据原始目录树中的位置来命名文件并复制它们。例如(“:”在文件名中是合法的,但不常见),您的“find”命令可以调用一个shell脚本(而不是直接使用“cp”),该脚本可能如下所示:
#!/bin/sh
case "x$1" in
x/volume1/tv/_FANART/*)
    ;;
*)
    target=`echo "$1" | sed -e 's,^/volume1/tv/,,' -e s,/,:,g`
    cp "$1" "$2/$target"
    ;;
esac

而相应的“-exec”将是:

-exec myscript "{}" /volume1/tv/_FANART \;

顺便提一下,原始示例中的源/目标位于相同的目录树“/volume1/tv”,这就是为什么示例脚本使用case语句的原因-排除已复制到_FANART文件夹中的文件。

冒号并不是唯一有用的标点符号,还有几个“合理”的选择,包括“@”、“+”——权衡的是字符是否存在于文件名中(使其具有碰撞的机会),而在shell脚本中使用的便利性。 - Thomas Dickey
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Thomas Dickey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接