9

I want to write the following bash function in a way that it can accept its input from either an argument or a pipe:

b64decode() {
    echo "$1" | base64 --decode; echo
}

Desired usage:

$ b64decode "QWxhZGRpbjpvcGVuIHNlc2FtZQ="
$ b64decode < file.txt
$ b64decode <<< "QWxhZGRpbjpvcGVuIHNlc2FtZQ="
$ echo "QWxhZGRpbjpvcGVuIHNlc2FtZQ=" | b64decode
  • 2
    seems like a pointless function when base64 and bash can do all that anyway. why write a function just to avoid using the -d or --decode option? if you really must have something called b64decode then alias b64decode='base64 --decode'. b64d would be shorter, though and save even more typing. – cas Aug 5 '16 at 13:47
  • 2
    You are right, this was just used as an example, though. – tyrondis Aug 5 '16 at 22:45
12

You can use /dev/stdin to read from standard input

b64decode()
{
    if (( $# == 0 )) ; then
        base64 --decode < /dev/stdin
        echo
    else
        base64 --decode <<< "$1"
        echo
    fi
}
  • $# == 0 checks if number of command line arguments is zero
  • base64 --decode <<< "$1" one can also use herestring instead of using echo and piping to base64
  • 1
    just a clean syntax imo, echo and pipe might be faster.. see unix.stackexchange.com/questions/59007/… and it is herestring, I made a mistake – Sundeep Aug 5 '16 at 4:49
  • 2
    You could pipe the input through tr -d "\n" to remove lines breaks. – Julie Pelletier Aug 5 '16 at 5:51
  • 2
    does base64 support multiple input lines? of course it does, it would be pretty useless if it didn't. see for yourself: ls -l /usr/bin/ | base64 | base64 -d – cas Aug 5 '16 at 13:43
  • 1
    btw, +1. yours is a good answer to a question that only makes any sense if it's just a standin for much more complicated function. – cas Aug 5 '16 at 13:53
  • 4
    You don't actually need the < /dev/stdin; without a file, base64 will simply read from the standard input it inherits from its parent, which is /dev/stdin. – chepner Aug 6 '16 at 0:35
0

Sundeep's answer works for base64 because that utility does not support multiple lines. A more general fix for the more general case

is something like

my_function() {
    if (( ${#} == 0 )) ; then
        while read -r line ; do
            target_utility "${line}"
        done
    else
        target_utility "${@}"
    fi
}

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.