3

I actually try to run recursive through a folder structure and make md5sum on all files into a single md5checksums file.

Heres my script:

#!/bin/bash
rm -f md5checksums
find -type f -exec md5sum "{}" + > md5checksums

My problem now is that the file md5checksums is aswell running through md5sum and i cant get my head around it how to prevent that. Beside that the script does already what it should do. Anyone who can help me out?

  • 2
    Simple way: keep your md5checksums file in the parent directory. – muru Apr 10 '16 at 20:06
  • Well that doesn really cut it, i have not in all cases access to the parent directory, and aswell running md5sum -c md5checksums from parent directory would fail all files because of wrong paths. – Videonauth Apr 10 '16 at 20:15
  • If you stored it in the parent directory, you'd obviously run md5sums -c ../md5checksums, wouldn't you? – muru Apr 10 '16 at 20:16
  • sure, just like i said i not have in all cases i need that script the ability to access and write into parent – Videonauth Apr 10 '16 at 20:20
3

make the script take the name of that specific file you want excluded as argument.

#!/bin/bash
rm -f md5checksums
find -type f ! -iname "$1" -exec md5sum "{}" + > md5checksums

call the script with ./script "md5checksums"

  • 1
    Thats what i was looking for :) changed my line to find -type f ! -iname "md5checksums" -exec md5sum "{}" + > md5checksums and now it works like a breeze, thank you – Videonauth Apr 10 '16 at 20:24
  • 2
    why -iname instead of -name? why even have it as an argument, when the name of the file is md5checksums? – tlund Apr 10 '16 at 20:27
  • You missed the little ! which means not also is aswell equal to -not -name. But to be honest i kinda feel embarassed that i wasnt able to stumble onto that simple solution on my own. – Videonauth Apr 10 '16 at 20:31
  • @tlund : I put the -iname instead of -name just in case he calls the script with the file name in all caps or something. but since he prefers to have the filename hardcoded in the script it makes no difference :) I made the script take the filename as an argument in case the filename was something not consistent every time he calls his hash script. – user257256 Apr 10 '16 at 20:35
2

The simplest way to avoid conflicts involving redirections to a file affecting the command would be to use sponge from moreutils:

sponge  reads  standard  input and writes it out to the specified file.
Unlike a shell redirect, sponge soaks up all its input  before  opening
the  output file. This allows constructing pipelines that read from and
write to the same file.

The effect is that the file, if not present already, isn't created until the pipeline finishes. So:

find . -type f -exec md5sum {} + | sponge md5checksums
2

Using only bash:

Using GLOBIGNORE:

$ GLOBIGNORE='md5checksums'  ## Pattern to ignore
$ shopt -s globstar  ## Recursive globbing
$ { for i in **/*; do [ -f "$i" ] && md5sum "$i"; done ;} >md5checksums

Using extglob:

$ shopt -s extglob ## Enables extended pattern matching, enabled by default
$ shopt -s globstar
$ { for i in **/!(md5checksums); do [ -f "$i" ] && md5sum "$i"; done ;} >md5checksums

Using zsh:

% setopt extended_glob 
% { for i in **/^md5checksums(.); do md5sum "$i"; done  ;} >md5checksums
  • zsh does recusive matching by default while using **

  • ^md5checksums is zsh extended glob pattern, meaning to match everything else except md5checksums

  • The glob qualifier (.) restricts matches to regular files only.

1

Another one that do what you want:

#!/bin/bash
rm -f md5checksums
find -type f -not -name "md5checksums" -exec md5sum "{}" + > md5checksums
1

Thanks to @heemayl for some nice inspiration in his answer.

#!/bin/bash

shopt -s globstar

rm -f md5checksums

for i in **/*; do
    if [ ! -f "$i" -o "$i" = md5checksums -o "$i" = this_script.sh ]; then
        continue
    else
        md5sum "$i" >> md5checksums
    fi
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.