Generate MD5sum for all files in a directory, and then write (filename).md5 for each file containing that file's MD5SUM

12,820

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 {} +
Share:
12,820

Related videos on Youtube

Matthew
Author by

Matthew

Updated on September 18, 2022

Comments

  • Matthew
    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
    telcoM over 6 years
    Looks OK, but you're restricting it to .iso files.
  • Kusalananda
    Kusalananda over 6 years
    Parses output of ls and uses unquoted variable expansions.
  • Ming Jia
    Ming Jia over 6 years
    Can you explain your comments? you can replace ls with find or any other command.
  • Kusalananda
    Kusalananda over 6 years
    Assume 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
    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 have ambiguous redirect error. Try var="with space.txt"; echo "hi" > $var and then var="with space.txt"; echo "hi" > "$var"
  • Sergiy Kolodyazhnyy
    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
    Kusalananda over 6 years
    Yeah, 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...