将文件重命名为哈希和扩展名
Posted
技术标签:
【中文标题】将文件重命名为哈希和扩展名【英文标题】:Rename files to hash and extension 【发布时间】:2017-12-19 17:18:47 【问题描述】:该问题已根据 OP 的喜好回答 here,但我无法使其 100% 为我工作。我想要做的是在/home/hermit/Documents/Pictures
中获取文件并在将新文件放入/home/hermit/Documents/HashPictures
之前对其进行哈希处理,同时将文件保留在/home/hermit/Documents/
中。不幸的是,该解决方案不似乎适用于 GIF 和 JPG。
或者 GNU sed 可以做得更短:
# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v \2 \1\3/e'
如果我可以有一个易于阅读的脚本或附有脚本的解释,那将是一件很好的事情。
编辑:这些是剩余文件(在/home/hermit/Documents/Pictures
和终端输出中。剩余文件:File names inside
hermit@hermit:~/Documents/PicturesHashed$ ./hash.sh
mv: target '9c48b6846aa3211ba867d9775aa9a730.jpg' is not a directory
mv: target '6cef7445eb7382aa719e364dc2d0126c.jpg' is not a directory
mv: target 'b3624eae0010f7d042af838859d5ea0e.png' is not a directory
mv: target '12f8f700cc73abe05da61103184f2ed0.jpg' is not a directory
mv: target '340e018ba57016f469a1039fb19c2619.jpg' is not a directory
mv: target '89da545ea3084500cd86a6265676173c.jpg' is not a directory
mv: target '7ff0671fc0447ca009d216670a0e2ac9.gif' is not a directory
mv: target '300d7e1e9807701f1a5043de85992484.jpg' is not a directory
mv: target 'c340521eec897957c0a7d6f415232ae4.png' is not a directory
mv: target '263ef6fd0b8623227a705bbcecb61755.gif' is not a directory
mv: target '2f4e522461ff467d5b4a09b7d33c2114.jpg' is not a directory
mv: target '2372edeb385381540d2230266ad5a4d2.png' is not a directory
mv: target 'bf5fc13be51d281347e0b00694c7689b.jpg' is not a directory
mv: target '3ab04030a8d06ff5aa5dca406c3927b0.jpg' is not a directory
mv: target '84d61abe2ff50e81d96e9b5ca916048e.jpg' is not a directory
mv: target 'c1c74496d880e4a20403c65e583dff54.jpg' is not a directory
mv: target '99c2a10e1f4ce27a08eafb70cbac09c1.jpg' is not a directory
mv: target '7ff0671fc0447ca009d216670a0e2ac9.gif' is not a directory
mv: target 'e27c3fe527a6417e13f2b55865b77d4f.jpg' is not a directory
mv: target 'd32b6aa0ff3929b477fe5e33872220d1.png' is not a directory
mv: target '70df8a56449a7b19b286e0b77394a7c8.jpg' is not a directory
mv: target '7e9b7446ea3fe662fa7ba3ba45952cbf.jpg' is not a directory
mv: target '975de97e64c345cbe41532101636c70e.gif' is not a directory
mv: target 'c3a691daa3400f00c87de37703ddd222.jpg' is not a directory
sh: 1: Syntax error: "(" unexpected
sh: 1: Syntax error: "(" unexpected
mv: target 'ce14ef4371c5fe6a61a539a9f22e6227.jpg' is not a directory
【问题讨论】:
“似乎不起作用”是什么意思?你能举个例子说明你想要发生的事情吗? 这段代码不关心文件类型我怀疑你的问题是不同的。文件名中可能有空格。 新信息。而且,看来你是对的,菲利普·库林。如何让脚本适应特殊字符? 正则表达式经常被描述为只写代码。我认为这是一个很好的例子。 还有其他方法吗?我还没有上过编程课,正如我所说,这不是我的代码。 :P 【参考方案1】:我觉得这更容易阅读和理解:
#!/bin/bash
source_dir=/home/hermit/Documents/Pictures
destination_dir=/home/hermit/Documents/HashPictures
for file in "$source_dir"/*;do
hash=$(md5sum "$file"|cut -d' ' -f1)
ext=$file##*.
cp -v "$file" "$destination_dir/$hash.$ext"
done
【讨论】:
感谢您的解决方案!虽然解释会很好,但我觉得即使不知道语法,我也能理解这一点。【参考方案2】:Perl 的救援:
#!/usr/bin/perl
use warnings;
use strict;
use Digest::MD5 qw md5_hex ;
my ($source, $target) = @ARGV;
$source =~ s/(\s)/\\$1/g;
for my $file (glob "$source/*")
open my $fh, '<', $file or die "$file: $!";
my $content = do local $/; <$fh> ;
my $digest = md5_hex($content);
my ($extension) = $file =~ /\.([^.]*)/;
open my $out, '>', "$target/$digest.$extension" or die "$file: $!";
print $out $content;
close $out;
运行方式
perl script-name -- "source-dir" "target-dir"
【讨论】:
【参考方案3】:A 部分 - 你所看到的
或者 GNU sed 可以做得更短:
# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v \2 \1\3/e'
我个人讨厌在这些情况下使用sed
,如果让我在专业代码中进行审查,我会拒绝它,因为未来的读者很难理解。
Sed 是一个流编辑器。您将内容输入其中并对其进行编辑,然后将结果推出。它使用regular expressions 来匹配其输入的模式,然后对它们做一些事情。即使您已经使用了一段时间正则表达式也很难阅读,所以我不希望很多人能够阅读上面的代码。人们倾向于使用它,因为它可以用很少的代码做很多事情。
Sed 有很多派对技巧,在这种情况下,它被用来执行其他命令 (mv
)。
md5sum *
正在产生如下输出:
263620ac1a08b934b5312f416fe7a1af IMAG0001.jpg
972eddbf8e368a9c3d38e66bcf924cbc IMAG0002.jpg
94b30dfedb8afb7143268d1c329d7e64 IMAG0004.jpg
c592b83172e7f3c2d20207ee4e0cdd0d IMAG0005.jpg
1bc861c1251d87aea5e98ff263e09e79 IMAG0223.jpg
560afa8d60ff833a9dee52eff2fc420b IMAG0224.jpg
然后 Sed 将其编辑为如下所示:
mv -v IMAG0001.jpg 263620ac1a08b934b5312f416fe7a1af.jpg
mv -v IMAG0002.jpg 972eddbf8e368a9c3d38e66bcf924cbc.jpg
mv -v IMAG0004.jpg 94b30dfedb8afb7143268d1c329d7e64.jpg
mv -v IMAG0005.jpg c592b83172e7f3c2d20207ee4e0cdd0d.jpg
mv -v IMAG0223.jpg 1bc861c1251d87aea5e98ff263e09e79.jpg
mv -v IMAG0224.jpg 560afa8d60ff833a9dee52eff2fc420b.jpg
然后 Sed 正在执行此代码。
现在您明白了,您很可能会选择 mv -v
并将其换成 cp
或其他命令。但是你仍然会遇到空格和特殊字符的问题。
B 部分 - 更强大的解决方案
我会完全避免sed
。如果您不了解它,请不要使用它。大多数人不明白。
for file in *.jpg
do
sum=`md5sum "$file"`
#remove the file name from md5sum's output
# this is using bash's pattern matching but can be swapped out
sum="$sum% $file"
cp "$file" "HashPictures/$sum"
done
请注意,我在$file
和$sum
周围都加上了引号。此外,我们每个命令处理一个文件,而不是每个文件一个命令。这样,文件名中的空格就不会与用于分割命令参数的空格混淆。
C 部分 - 最后的想法
对于这个示例代码,我使用cp
将图像的副本放在新目录中。那可能不是你想要的。例如使用ln -s "$file" "HashPictures/$sum"
创建一个symbolic link。这样可以避免复制文件并节省大量空间。
【讨论】:
这是一个 bash/shell 脚本,对吧?此外,我可以看到该脚本可能无法同时适用于所有扩展。不过很好的解释。 感谢您的解决方案,菲利普·库林!很好的解释。 当然。 bash / sh 如果您将*.jpg
更改为*
,它将捕获所有扩展名。【参考方案4】:
这是一个 Python 解决方案。把它放在你要转换的同一目录下的 Python 文件中(或修改'.'
)。
import hashlib
import os
def file_as_bytes(file):
with file:
return file.read()
def hash_file(fpath):
return hashlib.md5(file_as_bytes(open(fpath, 'rb'))).hexdigest()
for fname in os.listdir('.'):
name, ext = os.path.splitext(fname)
hash = hash_file(fname)
dst = hash + ext
print(fname + " --> " + dst)
os.rename(fname, dst)
【讨论】:
【参考方案5】:将当前目录中所有非目录的文件重命名为
md5sum * | awk 'print "mv", $2, $1 ".jpg" ' | bash
或
md5sum -- * | awk 'print "mv --", $2, $1 ".jpg" ' | bash
如果文件以减号开头。
【讨论】:
以上是关于将文件重命名为哈希和扩展名的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 7 上将文件重命名为 md5 sum + 扩展名(使用 CMD 或 PowerShell 2013)