How can I avoid using a temporary file in this bash script?

1.1k views Asked by At

As a beginner with shell scripting, I've written this bash script function to return the md5sum of a file, while providing the user with a GUI progress bar.

md5sum_of_file () {
    (pv -n $1 | md5sum | sed -e 's/\s.*//g' > /tmp/md5sum) 2>&1 | zenity --progress --auto-close
    echo $(</tmp/md5sum)
    rm /tmp/md5sum
}

pv -n $1 feeds the file into md5sum | sed -e 's/\s.*//g' (sed strips the output of the sum's associated filename), while piping a percentage to zenity --progress --auto-close.

I know you can't simply assign the checksum to a variable in this instance, as "(pv -n $1 | $(md5sum | sed -e 's/\s.*//g'))" is within its own subshell. But is there a way to do this without creating a temporary file (in this case "/tmp/md5sum")?

Thanks.

2

There are 2 answers

0
chepner On BEST ANSWER

The only thing that zenity is using is the standard error from pv, so use a process substitution to do that without involving any stdout or stderr from the other commands. This lets the output of sed simply go to standard output without the need for any temp files.

pv -n "$1" 2> >(zenity --progress --auto-close) | md5sum | sed -e 's/\s.*//g'
0
gniourf_gniourf On

I guess this will do (with Bash):

md5sum_of_file() {
    local md5sum
    read -r md5sum _ < <( { { pv -n "$1" | md5sum >&3; } 2>&1 | zenity --progress --auto-close; } 3>&1)
    echo "$md5sum"
}

We're doing a little bit of plumbing here:

  • pv's standard output (i.e., the content of the file) is normally passed to md5sum, and md5sum's output is redirected to file descriptor 3;
  • the standard error stream of pv is then redirected to standard output to be fed to zenity;
  • after this, we redirect file descriptor 3 (remember, it's md5sum's output) to standard output, to be read by read;
  • read only reads the first field of that (so that we don't need sed to cut the filename);
  • finally, we echo the result.

If your function only does that (that is, you only want to echo the md5 sum), you could also do it thus:

md5sum_of_file() {
    { { pv -n "$1" | md5sum >&3; } 2>&1 | zenity --progress --auto-close; } 3>&1 | { read -r md5sum _; echo "$md5sum"; }
}