![将目录中的所有文件重命名为其文件名的 md5 哈希值(不是内容)](https://linux22.com/image/117922/%E5%B0%86%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E6%96%87%E4%BB%B6%E9%87%8D%E5%91%BD%E5%90%8D%E4%B8%BA%E5%85%B6%E6%96%87%E4%BB%B6%E5%90%8D%E7%9A%84%20md5%20%E5%93%88%E5%B8%8C%E5%80%BC%EF%BC%88%E4%B8%8D%E6%98%AF%E5%86%85%E5%AE%B9%EF%BC%89.png)
我对 linux / 命令行非常陌生,需要加密 10K+ 文件的名称(唯一名称),以便它们与 mySQL 数据库中的 MD5 加密名称匹配。
我已经了解了如何重命名文件目录以及如何获取文件的哈希值(mdsum?)但我坚持如何获取文件名的哈希,然后将该文件重命名为生成的哈希,保留扩展名 ie
mynicepicture.jpg > fba8255e8e9ce687522455f3e1561e53.jpg
看起来它应该是一个简单的重命名或mv
行,但我无法理解它。
非常感谢您的见解
PS 我已经在一些接近我正在寻找的示例中看到了 Perl 函数的使用,但不知道在哪里/如何使用它们。
答案1
你没有说你想使用哪个外壳,所以我只是假设重击– 答案需要调整才能与其他 shell 一起使用。
for i in *; do sum=$(echo -n "$i"|md5sum); echo -- "$i" "${sum%% *}.${i##*.}"; done
脚本版本:
for i in *; do
sum=$(echo -n "$i" | md5sum)
echo -- "$i" "${sum%% *}.${i##*.}"
done
这个简单的for
循环获取当前目录中的每个文件,计算其名称的 md5 和并将其输出。使用它来检查功能,如果您想开始重命名,请将第二个替换echo
为mv
.
说明
echo -n "$i" | md5sum
– 计算 md5 和完整文件名包括文件扩展名(管道),将扩展名更改echo -n "$i"
为以下之一:${i%%.*} sed 's/\..*//' <<< "$i" echo "$i" | sed 's/\..*//'
sum=$(…)
– 执行…
并将输出保存在$sum
(命令替换)${sum%% *}
– 输出所有内容,直到第一个空格(参数替换),与以下之一相同:$(sed 's/ .*//' <<< "$sum") $(echo "$sum" | sed 's/ .*//')
${i##*.}
– 输出最后一个点之后的所有内容(参数替换),与以下之一相同:$(sed 's/.*\.//' <<< "$i") $(echo "$i" | sed 's/.*\.//')
如果需要在不同文件夹中递归地重命名文件,请使用find
与-exec
选项。
答案2
#!/bin/bash
md5name () {
local base=${1##*/}
local ext=${base##*.}
local dir=${1%/*}
printf '%s' "${base%.$ext}" | md5sum |
awk -v dir="$dir" -v ext="$ext" '{ printf("%s/%s.%s\n", dir, $1, ext) }'
}
dir=$HOME # where your files are
for pathname in "$dir"/*; do
test -f "$pathname" || continue
echo mv "$pathname" "$( md5name "$pathname" )"
done
该bash
脚本使用md5sum
GNU coreutils 中的实用程序根据任何给定路径名的基本名称(无扩展名)计算 MD5 哈希值。辅助函数md5name
执行实际计算,并将输出带有完整路径和扩展名的新名称。
该md5name
函数用于awk
根据给定路径名的部分和 的结果组装新名称md5sum
。
函数本身使用的示例:
$ md5name '/some/path/file name here.extension'
/some/path/c9e89fa443d16da4b96ea858881320c9.extension
...c9e89fa443d16da4b96ea858881320c9
字符串的 MD5 哈希值在哪里file name here
。
echo
从顶部的脚本中删除 来实际重命名文件。echo
如果您在某些时候需要将文件名恢复为其原始名称,您可能希望将原始脚本的输出保存到文件(就地)。
请注意,运行此两次在一组文件上将计算 MD5 哈希值的 MD5 哈希值,并且原始文件名将变得不可恢复,除非您仔细记录每次运行脚本后哪些文件的名称。
答案3
与perl
:rename
find . -name '*.jpg' -type f -exec rename -n '
BEGIN{use Digest::MD5 qw(md5_hex)}
my ($dir, $name, $ext) = m{(.*)/(.*)\.(.*)}s;
$_ = "$dir/" . md5_hex($name) . ".$ext"' {} +
(高兴时删除 -n
)。
答案4
对于一种AWK
方法:
find [Directory] -type f [various other find options] |
awk '{orig=$0;
match($0,/^.*\//,path); sub("^"path[0], "");
match($0, /.[[^.]+$/,ext); sub(ext[0]"$", "");
("echo \"" $0 "\"|md5sum") | getline;
com=sprintf("mv \"%s\" \"%s%s%s\"", orig, p[0], $1, ext[0]);
print(com)
}'
假定现代find
命令不需要输入目录.
,因此 [Directory] 可以留空。唯一-type f
的查找文件,这很方便,因为md5sum
不喜欢目录并且在运行时更改目录名称不是一个好主意。-iname pattern
如果您只想使用某些文件,请使用,例如-iname \*.dat
,如果大小写很重要,请使用-name
而不是-iname
。
这些match(...); sub(...)
片段提取文件名的部分并在输入字符串中替换它们。请注意, [pre/app] 附加"^"
和"$"
是为了防止替换可能重复路径/扩展名的字符串。
替换print(com)
为system(com)
实际执行重命名,例如:
find -type f |
awk '{orig=$0;
match($0,/^.*\//,path); sub("^"path[0], "");
match($0, /.[[^.]+$/,ext); sub(ext[0]"$", "");
("echo \"" $0 "\"|md5sum") | getline;
com=sprintf("mv \"%s\" \"%s%s%s\"", orig, p[0], $1, ext[0]);
system(com)
}'
如果您想使用md5sum
实际文件的名称作为名称md5sum
您可以利用输出总和和输入文件名的事实来执行以下操作:
find -type f -exec md5sum '{}' ';' |
while read sum file ; do
[echo] mv "$file" "`dirname $file`/$sum".extension ;
done
将while read sum file
采用 2 个参数,即命令的结果md5sum
,并使用它们进行赋值sum
和变量。file
由于sum
其中不应有空格,因此read
应该可以正常工作。
显然,[echo]
在实际运行时应该将其删除,但在运行之前测试任何脚本更改以测试搜索时,这始终是一个好主意。
这一切都假设你正在跑步bash
。另外,这可以输入为较长的一行:
find -iname \*.jpg -exec md5sum '{}' ';' | while read sum file ; do mv "$file" "`dirname $file`/$sum".jpg ; done