我在某个文件夹中有一个没有扩展名的文件列表。我想重命名它们并添加扩展名。该名称应该是 UUID。我知道如何找到它们,并且有用于生成 UUID 的实用程序“uuidgen”,我该怎么做剩下的事情?
find . -type f -name 'file*' # ??? -exec .... ???
答案1
尝试:
find . -type f -name 'file*' -execdir sh -c 'mv "$1" "$(uuidgen).ext"' Renamer {} \;
怎么运行的
find . -type f -name 'file*' -execdir ... \;
您似乎熟悉这部分:它查找名称与 glob 匹配的文件
file*
,并对它们运行命令...
,在我们的例子中,...
替换为:sh -c 'mv "$1" "$(uuidgen).ext"' Renamer {}
这将启动一个 shell,运行 mv 命令,并使文件名可用为
$1
. (Renamer
是 shell 分配给的任意字符串,$0
如果生成错误消息,shell 将使用该字符串。)该find
命令将替换{}
为它找到的文件名,这就是 shell 分配给的内容$1
。我们只看一下 shell 命令:mv "$1" "$(uuidgen).ext"
这会将文件从
$1
重命名为由uuidgen
.由于文件名可能包含空格或其他困难字符,因此我们将其放在
$1
双引号中以保护名称免受分词或 shell 扩展的影响。
我们使用-execdir
而不是-exec
出于两个原因:
它使
mv
命令更容易:不需要额外的代码来确保重命名的文件保留在同一目录中。-execdir
更安全:如果目录被重命名尽管该find
命令正在运行,-exec
但没有运行-execdir
,可能会严重失败。
为什么要启动一个新的 shell?
尝试使用可能很诱人:
find . -type f -name 'file*' -execdir mv {} "$(uuidgen).ext" \; # Don't do this
这里的问题是uuidgen
只能运行一次。 shell 会运行uuidgen
前它甚至启动find
命令。因此,所有mv
命令都将具有相同的目标文件名。我们想跑uuidgen
一次每一个找到的文件find
。这就是为什么我们需要在命令下运行mv
and 。uuidgen
sh
更高效的版本
上面的代码为找到的每个文件启动一个新的 shell。相比之下,以下方法可以在每个启动的 shell 进程中处理数千个文件:
find . -type f -name 'fi*' -execdir sh -c 'for f; do mv "$f" "$(uuidgen).ext"; done' Renamer {} +