Ble*_*ley 15 bash md5 for-loop directory-structure find
我有一个结构如下的目录:
.
??? Test.txt
??? Test1
? ??? Test1.txt
? ??? Test1_copy.txt
? ??? Test1a
? ??? Test1a.txt
? ??? Test1a_copy.txt
??? Test2
??? Test2.txt
??? Test2_copy.txt
??? Test2a
??? Test2a.txt
??? Test2a_copy.txt
Run Code Online (Sandbox Code Playgroud)
我想创建一个bash脚本,对该目录中的每个文件进行md5校验和.我希望能够在CLI中键入脚本名称,然后输入我想要哈希的目录的路径并让它工作.我确信有很多方法可以实现这一目标.目前我有:
#!/bin/bash
for file in "$1" ; do
md5 >> "${1}__checksums.md5"
done
Run Code Online (Sandbox Code Playgroud)
这只是挂起而且不起作用.也许我应该使用find?
一个警告 - 我想要哈希的目录将包含具有不同扩展名的文件,并且可能并不总是具有完全相同的树结构.我想要一些能在这些不同情况下起作用的东西.
TeW*_*eWu 29
md5deep
md5deep -r path/to/dir > sums.md5
Run Code Online (Sandbox Code Playgroud)
find
和md5sum
find relative/path/to/dir -type f -exec md5sum {} + > sums.md5
Run Code Online (Sandbox Code Playgroud)
请注意,当您运行检查MD5总和时md5sum -c sums.md5
,需要从生成sums.md5
文件的同一目录运行它.这是因为find
输出路径相对于您当前的位置,然后将其放入sums.md5
文件中.
如果这是一个问题,你可以做出relative/path/to/dir
绝对的(例如,通过$PWD/
放在你的路径前).这样您就可以sums.md5
从任何位置运行检查.缺点是,现在sums.md5
包含绝对路径,这使它更大.
find
和md5sum
您可以将此函数放入您的.bashrc
文件(位于您的$HOME
目录中):
function md5sums {
if [ "$#" -lt 1 ]; then
echo -e "At least one parameter is expected\n" \
"Usage: md5sums [OPTIONS] dir"
else
local OUTPUT="checksums.md5"
local CHECK=false
local MD5SUM_OPTIONS=""
while [[ $# > 1 ]]; do
local key="$1"
case $key in
-c|--check)
CHECK=true
;;
-o|--output)
OUTPUT=$2
shift
;;
*)
MD5SUM_OPTIONS="$MD5SUM_OPTIONS $1"
;;
esac
shift
done
local DIR=$1
if [ -d "$DIR" ]; then # if $DIR directory exists
cd $DIR # change to $DIR directory
if [ "$CHECK" = true ]; then # if -c or --check option specified
md5sum --check $MD5SUM_OPTIONS $OUTPUT # check MD5 sums in $OUTPUT file
else # else
find . -type f ! -name "$OUTPUT" -exec md5sum $MD5SUM_OPTIONS {} + > $OUTPUT # Calculate MD5 sums for files in current directory and subdirectories excluding $OUTPUT file and save result in $OUTPUT file
fi
cd - > /dev/null # change to previous directory
else
cd $DIR # if $DIR doesn't exists, change to it to generate localized error message
fi
fi
}
Run Code Online (Sandbox Code Playgroud)
运行后source ~/.bashrc
,您可以使用md5sums
正常的命令:
md5sums path/to/dir
Run Code Online (Sandbox Code Playgroud)
将checksums.md5
在path/to/dir
目录中生成文件,其中包含此目录和子目录中所有文件的MD5总和.使用:
md5sums -c path/to/dir
Run Code Online (Sandbox Code Playgroud)
从path/to/dir/checksums.md5
文件中检查总和.
注意,path/to/dir
可以是相对的或绝对的,md5sums
无论哪种方式都可以正常工作.生成的checksums.md5
文件始终包含相对于的路径path/to/dir
.您可以使用不同的文件名,然后checksums.md5
通过提供-o
或--output
选项默认使用.所有的选项,其他然后-c
,--check
,-o
并--output
传递给md5sum
.
md5sums
函数定义的前半部分负责解析选项.有关它的更多信息,请参阅此答案.下半部分包含解释性意见.
怎么样:
find /path/you/need -type f -exec md5sum {} \; > checksums.md5
更新#1:根据@twalberg 的建议改进了命令以处理文件名中的空格。
更新#2:根据@jil 的建议进行改进,删除不必要的xargs
调用和使用-exec
find 选项。
更新#3: @Blake 一个简单的脚本实现看起来像这样:
#!/bin/bash
# Usage: checksumchecker.sh <path>
find "$1" -type f -exec md5sum {} \; > "$1"__checksums.md5
Run Code Online (Sandbox Code Playgroud)
更新答案
如果您喜欢下面的答案或任何其他答案,您可以创建一个函数来为您执行该命令。因此,要测试它,请在终端中输入以下内容来声明函数:
function sumthem(){ find "$1" -type f -print0 | parallel -0 -X md5 > checksums.md5; }
Run Code Online (Sandbox Code Playgroud)
然后你就可以使用:
sumthem /Users/somebody/somewhere
Run Code Online (Sandbox Code Playgroud)
如果您喜欢的话,您可以将该行添加到“bash 配置文件”的末尾,并且该函数将在您登录时声明并可用。您的“bash 配置文件” 可能位于$HOME/.profile
原答案
为什么不让所有 CPU 核心并行工作呢?
find . -type f -print0 | parallel -0 -X md5sum
Run Code Online (Sandbox Code Playgroud)
-type f
这会查找当前目录 ( ) 中的所有文件 ( .
) 并在末尾打印空字节。然后将它们传递给GNU Parallel,它被告知文件名以空字节 ( -0
) 结尾,并且它应该一次处理尽可能多的文件 ( -X
) 以节省为每个文件创建一个新进程,并且应该 md5sum文件。
对于像 Photoshop 文件这样的大图像,这种方法将在速度方面带来最大的好处。
归档时间: |
|
查看次数: |
21231 次 |
最近记录: |