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

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

如果文件以减号开头。

【讨论】:

以上是关于将文件重命名为哈希和扩展名的主要内容,如果未能解决你的问题,请参考以下文章

将文件重命名为 md5 sum + 扩展名 (BASH)

linux 重命名文件和文件夹

linux 重命名文件和文件夹

linux 重命名文件和文件夹

在 Windows 7 上将文件重命名为 md5 sum + 扩展名(使用 CMD 或 PowerShell 2013)

如何使用 mv 命令重命名 unix 中的多个文件?