我有一个像这样结构的目录:
.
├── 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
我想创建一个bash脚本,对该目录中的每个文件进行md5校验和。我希望能够在CLI中键入脚本名称,然后输入我想要哈希的目录的路径并让它工作。我确信有很多方法可以实现这一目标。目前我有:
#!/bin/bash
for file in "$1" ; do
md5 >> "${1}__checksums.md5"
done
这只是挂起而且无法正常工作。也许我应该使用find?
一个警告 - 我想要哈希的目录将包含具有不同扩展名的文件,并且可能并不总是具有完全相同的树结构。我想要一些能在这些不同情况下起作用的东西。
答案 0 :(得分:23)
$ java -jar bin/pdfboxer-0.0.1.jar \
-trimBox 7.200000,7.200000,504.000031,720.000000 \
-artBox 7.200000,7.200000,504.000031,720.000000 \
-sourceFile src/test/pdfs/UNTRIMMED_PDF.pdf \
-destFile src/test/pdfs/TRIMMED_PDF.pdf
md5deep
md5deep -r path/to/dir > sums.md5
和find
md5sum
请注意,当您使用find relative/path/to/dir -type f -exec md5sum {} + > sums.md5
检查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
}
后,您可以像正常命令一样使用source ~/.bashrc
:
md5sums
将在md5sums path/to/dir
目录中生成checksums.md5
文件,其中包含此目录和子目录中所有文件的MD5总和。使用:
path/to/dir
检查md5sums -c path/to/dir
文件的总和。
请注意path/to/dir/checksums.md5
可以是相对的或绝对的,path/to/dir
无论如何都可以正常工作。生成的md5sums
文件始终包含相对于checksums.md5
的路径。
您可以通过提供path/to/dir
或checksums.md5
选项使用不同的文件名,然后使用默认-o
。除--output
,-c
,--check
和-o
之外的所有选项都会传递给--output
。
md5sum
函数定义的前半部分负责解析选项。有关它的更多信息,请参阅this answer。下半部分包含解释性意见。
答案 1 :(得分:4)
怎么样:
find /path/you/need -type f -exec md5sum {} \; > checksums.md5
更新#1:根据@ twalberg的建议改进了命令,以处理文件名中的空格。
更新#2 :根据@ jil的建议进行了改进,删除了不必要的xargs
电话,并改为使用-exec
选项。
更新#3: @Blake您的脚本的简单实现看起来像这样:
#!/bin/bash
# Usage: checksumchecker.sh <path>
find "$1" -type f -exec md5sum {} \; > "$1"__checksums.md5
答案 2 :(得分:1)
#!/bin/bash
shopt -s globstar
md5sum "$1"/** > "${1}__checksums.md5"
说明:shopt -s globstar
(manual)启用**
递归glob通配符。这意味着"$1"/**
将在作为参数$1
给出的目录下递归地扩展到所有文件的列表。然后,脚本只需使用此文件列表作为参数调用md5sum
,> "${1}__checksums.md5"
将输出重定向到文件。
答案 3 :(得分:1)
更新了答案
如果您喜欢下面的答案或其他任何答案,您可以创建一个为您执行命令的功能。因此,要测试它,请在Terminal中键入以下内容以声明一个函数:
function sumthem(){ find "$1" -type f -print0 | parallel -0 -X md5 > checksums.md5; }
然后你可以使用:
sumthem /Users/somebody/somewhere
如果您喜欢这种方式,可以将该行添加到&#34; bash配置文件&#34; 的末尾,只要您登录,该功能就会被声明并可用。您的&#34; bash个人资料&#34; 可能在$HOME/.profile
原始答案
为什么不让所有CPU内核并行工作?
find . -type f -print0 | parallel -0 -X md5sum
这将查找当前目录(-type f
)中的所有文件(.
),并在结尾处使用空字节打印它们。然后将这些传递给 GNU Parallel ,告知文件名以空字节(-0
)结尾,并且它应该一次执行尽可能多的文件({{ 1}})保存为每个文件创建一个新进程,它应该md5sum文件。
这种方法将在速度方面支付最大的奖励,包括像Photoshop文件这样的大图像。
答案 4 :(得分:1)
md5deep -r $your_directory | awk {'print $1'} | sort | md5sum | awk {'print $1'}
答案 5 :(得分:0)
使用查找命令列出目录树中的所有文件, 然后使用 xargs 为 md5sum 命令提供输入
find dirname -type f | xargs md5sum > checksums.md5