将文件重命名为哈希和扩展名

Rename files to hash and extension

问题的回答 here 符合 OP 的喜好,但我无法让它 100% 为我工作。我想要做的是在 /home/hermit/Documents/Pictures 中获取文件并在将新文件放入 /home/hermit/Documents/HashPictures 之前对其进行哈希处理,同时将文件保留在 /home/hermit/Documents/ 中。不幸的是,解决方案似乎不​​适用于 GIF 和 JPG。

Or GNU sed can do it even shorter:

# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v /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    

我觉得这更容易阅读和遵循:

#!/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

Perl 来拯救:

#!/usr/bin/perl
use warnings;
use strict;

use Digest::MD5 qw{ md5_hex };

my ($source, $target) = @ARGV;

$source =~ s/(\s)/\/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"

A 部分 - 您所见

Or GNU sed can do it even shorter:

# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v /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 或其他命令。但是您仍然会遇到 space 和特殊字符的问题。


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 两边都加上了引号。此外,我们每个命令处理一个文件,而不是每个文件一个命令。这样,文件名中的 space 永远不会与用于拆分命令参数的 space 混淆。


C 部分 - 最后的想法

对于此示例代码,我使用 cp 将图像的副本放在新目录中。那可能不是你想要的。例如使用 ln -s "$file" "HashPictures/$sum" 来创建 symbolic link。这将避免需要复制文件并节省大量 space.

这是一个 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)

将当前目录中所有非目录的文件重命名为

md5sum * | awk '{print "mv", ,  ".jpg"  }' | bash

 md5sum -- * | awk '{print "mv --", ,  ".jpg"  }' | bash

如果文件以缺点开头。