How do I use functions in bash?

I have a file with hashes of files against their filename. For example,

fb7e0a4408e46fd5573ffb9e73aec021a9dcf426235c0ccfc37d2f5e09a68a23 /path/to/some/file
237e0a4408e46fe3573f239e73aec021a9dcf426235c023fc37d2f5e09a68a12 /path/to/another/file
... and so on...

      

I need a hash converted to base64

encoded format.

So, I used a combination of bash function and awk

.

Here is what I wrote,

#!/bin/sh
base64Encode() {
     $1 | openssl base64 -A
}
awk ' { t = base64Encode $1; print t } ' file.txt

      

But it doesn't work. I am using hashdeep

hash list to generate file and hashdeep

does not support base64

encoded output. This is why I am using openssl

.

Any help or advice regarding this would be great!

Edit:

The given answers work, but I am having another problem.

Usually cat filename | openssl dgst -sha256 | openssl base64 -A

gives base64

encoded output for a file filename

, which is completely absurd, and output from hashdeep

consistent output from cat filename | openssl dgst -sha256

. So, I thought about dumping the output I got from the previous step onto openssl base64 -A

for output base64

. But still I get different values ​​from the actual result.

While it might be fine for an individual question, I would appreciate any support nonetheless.

+3


source to share


2 answers


Awk only:

$ awk '{ c="echo " $1 "|openssl base64 -A"
         c | getline r
         print r }' file
ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

      



For the rigid one-layer version, see @ 123's comment below.

... and @EdMorton is the super-fluid version (read: super-proof).

+1


source


Since you are especially asking how to use functions, I have split the problem into several small functions. This is good practice in all (large) bash programs.

Rule of thumb: functions behave like any other command:

  • you can redirect your I / O
  • you can call them with arguments
  • etc.

The best features are similar to regular unix executables, for example. reads from stdin and prints to stdout. This allows them to be used in pipelines as well.

So now rewrite:

# function for create base64 - reads from stdin, writes to stdout
base64Encode() {
        openssl base64 -A
}

# function for dealing with your file
# e.g. reads lines "hash path" and prints "base64 path"
convert_hashes() {
        while read -r hash path; do
                b64=$(base64Encode <<< "$hash")
                echo "$b64 $path"
        done
}

#the "main" program
convert_hashes < your_file.txt

      

Output

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo= /path/to/some/file
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo= /path/to/another/file

      

Yes, I know, I only want base64

without an attached path. From the course you can change the above convert_hashes

and remove the path from the exit, for example. instead echo "$b64 $path"

you can use echo "$b64"

and the output will only be a string b64

- but where you lose information in the function - which string belongs to which path - imho is not best practice.

Hence, you can leave the as-is function and use a different tool to get the first column - and only if needed - eg. in the "main" program. So you have developed a function for a later, more generic way.

convert_hashes < your_file.txt | cut -d ' ' -f1

      

Output

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

      

Now, imagine you are expanding your script and want to not use files, but the input comes from another program: let's simulate this with the following function get_data

(of course, in a real application this will do something different, not just cat

:

get_data() {
cat <<EOF
fb7e0a4408e46fd5573ffb9e73aec021a9dcf426235c0ccfc37d2f5e09a68a23 /path/to/some/file
237e0a4408e46fe3573f239e73aec021a9dcf426235c023fc37d2f5e09a68a12 /path/to/another/file
EOF
}

      



now you can use all of the above like:

get_data | convert_hashes

      

the output will be the same as above.

of course you can do something about the way out, let him say

get_data | convert_hashes | grep another/file | cut -d ' ' -f1
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

      

Of course, if you have such a "modular" structure, you can easily replace any parts, without having to touch other parts, for example, replacing openssl

with a command base64

.

base64Encode() {
        base64
}

      

And everything will go on without any changes. Of course, in a real application (perhaps) it is pointless to have a function that only calls one program, but I do this especially because you asked about functions.

Otherwise, the above can be made simple:

while read -r hash path; do
    openssl base64 -A <<<"$hash"
    echo
    #or echo $(openssl base64 -A <<<"$hash")
    #or printf "%s\n" $(openssl base64 -A <<<"$hash")
done < your_file.txt

      

or even

cut -d ' ' -f1 base  | xargs -I% -n1 bash -c 'echo $(openssl base64 -A <<<"%")'

      

You need echo

or print

because it openssl

doesn't print newlines by default. Output:

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

      

Ps: Honestly, I don't understand why you base64 encode some already encoded hash - but YMMV. :)

+1


source







All Articles