Generate MD5sum for all files in a directory, and then write (filename).md5 for each file containing that file's MD5SUM
Solution 1
cd /path/to/files &&
for file in *; do
if [[ -f "$file" ]]; then
md5sum -- "$file" > "${file}.md5"
fi
done
Solution 2
Redirection is an operator of the shell.
In:
find some args > {}.md5
find
is run with some args and its stdout redirected to {}.md5
.
Here, you'd need find
to start a shell to perform one redirection for each file:
find . -type f -exec sh -c '
for file do
md5sum "$file" > "$file.md5"
done' sh {} +
If you want to avoid the directory component in the .md5
part, you can either use the -execdir
alternatives supported by many find
implementations (though with some you'll still get a ./
directory component, and with some, that will still run one shell per file even with {} +
:
find . -type f -execdir sh -c '
for file do
md5sum "$file" > "$file.md5"
done' sh {} +
Or you can do it as:
find . -type f -exec sh -c '
for file do
(cd "${file%/*" && exec md5sum -- "${file##*/}") > "$file.md5"
done' sh {} +
Related videos on Youtube
Matthew
Updated on September 18, 2022Comments
-
Matthew almost 2 years
I have a directory full of files. Each file will be copied to a specific type of destination host.
I want to calculate an MD5 sum for each file in the directory, and store that md5 sum in a file that matches the name of the file that generated the sum, but with .md5 appended.
So, for instance, if I have a directory with:
a.bin b.bin c.bin
The final result should be:
a.bin a.bin.md5 # a.bin's calculated checksum b.bin b.bin.md5 # b.bin's calculated checksum c.bin c.bin.md5 # c.bin's calculated checksum
I have attempted this with find exec, and with xargs.
With find, I tried this command:
find . -type f -exec md5sum {} + > {}.md5
Using xargs, I tried this command:
find . -type f | xargs -I {} md5sum {} > {}.md5
In either case, I end up with a file called {}.txt, which isn't really what I am looking for.
Could anyone point out how to tweak these to generate the md5 files I am looking to generate?
-
telcoM over 6 yearsLooks OK, but you're restricting it to .iso files.
-
Kusalananda over 6 yearsParses output of
ls
and uses unquoted variable expansions. -
Ming Jia over 6 yearsCan you explain your comments? you can replace ls with find or any other command.
-
Kusalananda over 6 yearsAssume spaces in any of the names in the
files
directory, for example. Also consider what would happen if one of the names is a directory. -
Sergiy Kolodyazhnyy over 6 years@MingJia Parsing output of
ls
is considered generally bad practice (see this ). Even if there aren't any difficult filenames, that doesn't mean one shouldn't anticipate them. Second big problem is the$0
and$1
should be double-quoted. Because of "word splitting", if you have file with spaces or tabs in filename, ` > $1` will haveambiguous redirect
error. Tryvar="with space.txt"; echo "hi" > $var
and thenvar="with space.txt"; echo "hi" > "$var"
-
Sergiy Kolodyazhnyy over 6 years@MingJia Don't get discouraged, you'll learn to pick up on these things if you stick around on the site, with time of course. Welcome, to the site and consider re-working your answer.
-
Kusalananda over 6 yearsYeah, what he said. Sorry for being a bit short in my comments above. Your answer is welcomed, definitely, and I'm known to sometimes be a bit strict in my code reviews...