I am trying to make two functions in bash. One function that loops through a directories' contents and makes an md5 hash for each file storing them in an .md5 checksum file in the same directory. The other function to check that checksum file against it's directory contents. I am trying to keep the .md5 file standard which I believe is the md5 hash followed by the file name on one line for each file.
Requirements: I can only use the digest command for creating the hash; which errors on directories...
Ideally I can assume that the inbound files to archive are n number of non directory items. Nevertheless I want to be able to check the digest first for errors. Even if it fails for some unknown reason I can make another attempt before exiting the entire script with errors, or at least logging the inability to make a digest for that particular file and continuing.
Main Question: How can I if condition error check a command and also store the output in a variable?
Update: Solution Here
if ! digest -a md5 "$file" ; then ; fi
I attempted other variants such as piping to a temp file getting the variable and then removing the temp file, but that felt excessive for this task. I also looked into accessing the exit code using $? but based on what I have read in the past I am unsure of this communities solidarity on its use, let me know what you think.
Secondary Question: Is there a better way to achieve this?
Below are my current incomplete functions. Thanks!
function make_directory_md5 () {
local md5_file=$"$1/$(basename $1).md5"
local attempts=$(($2 - 1))
if [ ! -f "$md5_file" ] ; then
if ! touch "$md5_file" >> "$file_log" ; then
warning_handle "Could not make checksum file $md5_file, continuing anyway..."
if [ "$verbose_mode" = true ]; then verbose_handle "Checksum file $md5_file process failed." ; fi
else
if [ "$verbose_mode" = true ]; then verbose_handle "Checksum file $md5_file created..." ; fi
#Loop through file contents and get md5 and filename and output to checksum file
for file in "$1/*" ; do
if [ ! -d "$file" ] ; then
if [ ! "$file" = "$md5_file" ] ; then #Skip md5 file.
if ! hash="$(digest -a md5 $file)" >> "$file_log" ; then
warning_handle "Problem occured when attempting to digest $file"
if [ "$verbose_mode" = true ]; then verbose_handle "Attempting to try again, attempts left: $attempts" ; fi
if [ $attempts -ge 1 ]; then
make_directory_md5 $1 $attempts
else
warning_handle "Attempt to create checksum file $md5_file FAILED out of attempts."
local sucess=false
if ! rm "$md5_file" >> "$file_log" ; then
if [ -f "$md5_file" ] ; then
warning_handle "Could not remove $md5_file and it still exists!"
fi
else
if [ "$verbose_mode" = true ]; then verbose_handle "Removed $md5_file" ; fi
fi
fi
else
echo "$hash $file" >> "$md5_file"
fi
fi
else
warning_handle "Cannot hash directory! Skipping $file"
#Recursive decent into new directory. Or assume no directories ever...
fi
done
fi
else
warning_handle "Attempted to create checksum file $md5_file but it already exists..."
if [ "$verbose_mode" = true ]; then verbose_handle "Attempting to remove $md5_file..." ; fi
if ! rm "$md5_file" >> "$file_log" ; then
if [ -f "$md5_file" ] ; then
warning_handle "Could not remove $md5_file and it still exists. Continuing with backup..."
if [ "$verbose_mode" = true ]; then verbose_handle "Checksum file $md5_file process failed." ; fi
else
if [ "$verbose_mode" = true ]; then verbose_handle "Old checksum file $md5_file removed..." ; fi
if [ "$verbose_mode" = true ]; then verbose_handle "Attempting to try again, attempts left: $attempts" ; fi
if [ $attempts -ge 1 ] ; then
make_directory_md5 $1 $attempts
else
local sucess=false
warning_handle "Attempt to create checksum file $md5_file FAILED out of attempts."
if [ "$verbose_mode" = true ]; then verbose_handle "Checksum file $md5_file process failed." ; fi
fi
fi
else
if [ "$verbose_mode" = true ]; then verbose_handle "Old checksum file $md5_file removed..." ; fi
if [ "$verbose_mode" = true ]; then verbose_handle "Attempting to try again, attempts left: $attempts" ; fi
if [ $attempts -ge 1 ] ; then
make_directory_md5 $1 $attempts
else
local sucess=false
warning_handle "Attempt to create checksum file $md5_file FAILED out of attempts."
if [ "$verbose_mode" = true ]; then verbose_handle "Checksum file $md5_file process failed." ; fi
fi
fi
fi
}
function check_directory_md5 () {
local md5_file=$"$1/$1.md5"
for file in "$1"/. ; do
echo "$file"
done
}
make_directory_md5 "/home/jsharpe/out" 3
if ! OUTPUT="$(some commands here)"; then foo; fi
seems to work. – DopeGhoti Nov 20 '15 at 18:42md5sum
command might already do what you need, with the-c
flag. – user3188445 Nov 20 '15 at 18:51if ! FOO=$(/bin/true); then echo "then"; else echo "else"; fi
, I getelse
returned as expected; and I getthen
if I tryif
rather thanif !
. Using/bin/false
also works as expected for me. – DopeGhoti Nov 23 '15 at 17:542> /dev/null
or2> /path/to/error.log
. – DopeGhoti Nov 23 '15 at 18:33if ! hash="$(digest -a md5 $file 2>> "$file_log")"
my log file looks nice and my .md5 file appears to be working correctly. Now on to verifying. – JaredTS486 Nov 23 '15 at 19:41