165

I'm trying to base64 encode an image in a shell script and put it into variable:

test="$(printf DSC_0251.JPG | base64)"
echo $test
RFNDXzAyNTEuSlBH

I've also tried something like this:

test=\`echo -ne DSC_0251.JPG | base64\`

but still with no success.

I want to do something like this:

curl -v -X POST -d '{"image":$IMAGE_BASE64,"location":$LOCATION,"time_created":$TIMECREATED}' -H 'Content-type: text/plain; charset=UTF8' http://192.168.1.1/upload

I found this http://www.zzzxo.com/q/answers-bash-base64-encode-script-not-encoding-right-12290484.html

but still have had no success.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
dash00
  • 1,763
  • 2
  • 11
  • 4

8 Answers8

218

You need to use cat to get the contents of the file named 'DSC_0251.JPG', rather than the filename itself.

test="$(cat DSC_0251.JPG | base64)"

However, base64 can read from the file itself:

test=$( base64 DSC_0251.JPG )
chepner
  • 497,756
  • 71
  • 530
  • 681
  • with cat it works, great thanks a lot man. I know that it can read from file, but it still has problems to store it in variable so test="$(cat DSC_0251.JPG | base64)" works for me. – dash00 Jun 04 '13 at 13:21
  • 3
    What problems? The two commands above should produce identical results, except the first is a [useless use of cat](http://partmaps.org/era/unix/award.html). – chepner Jun 04 '13 at 13:27
  • you are right. This is what should I do `$RESPONSE="$(curl -v -X POST -d '{"image":\`base64|$DIR$IMAGE\`,"location":$LOCATION,"time_created":$TIMECREATED}' -H 'Content-type: text/plain; charset=UTF8' --max-time 180 -s $URL)";` – dash00 Jun 04 '13 at 13:51
  • I'm not a big Linux specialist, but isn't it a ` symbol that you should enclose command into to put results in variable? – David Jashi Jun 04 '13 at 13:53
  • 29
    `cat vlc.jpg | base64 -w 0 ` - in case someone want output as string to copy and paste. –  Mar 13 '14 at 10:45
  • @DavidJashi `$()` is very similar and easier to nest. – GKFX Aug 19 '16 at 12:54
  • 1
    What's wrong with `base64 DSC_0251.JPG`? There is no need to run through the `cat` filter when the program takes a file as arguments (`base64 [OPTIONS] [FILE]`) – Eric Feb 13 '18 at 08:39
  • @Eric Nothing; the first example just demonstrates what the OP was doing wrong by using `printf`; the second example does exactly what you suggest. – chepner Feb 13 '18 at 14:24
  • `< DSC_0251.JPG base64` would probably be a bit better than `cat` while maintaining the same left-to-right reading order. – Mateen Ulhaq Mar 13 '20 at 02:34
  • I only mentioned `cat` as a command that, unlike `printf`, reads the contents of a file before segueing to having `base64` read the file itself. I'm not away of any significant difference between `base64 DSC_0251.jpg` and `base64 < DSC_0251.jpg`. – chepner Mar 13 '20 at 11:17
115

Encode

On Linux

Single line result:

base64 -w 0 DSC_0251.JPG

For HTML:

echo "data:image/jpeg;base64,$(base64 -w 0 DSC_0251.JPG)"

As file:

base64 -w 0 DSC_0251.JPG > DSC_0251.JPG.base64

In variable:

IMAGE_BASE64="$(base64 -w 0 DSC_0251.JPG)"

In variable for HTML:

IMAGE_BASE64="data:image/jpeg;base64,$(base64 -w 0 DSC_0251.JPG)"

On OSX

On OSX, the base64 binary is different, and the parameters are different. If you want to use it on OSX, you should remove -w 0.

Single line result:

base64 DSC_0251.JPG

For HTML:

echo "data:image/jpeg;base64,$(base64 DSC_0251.JPG)"

As file:

base64 DSC_0251.JPG > DSC_0251.JPG.base64

In variable:

IMAGE_BASE64="$(base64 DSC_0251.JPG)"

In variable for HTML:

IMAGE_BASE64="data:image/jpeg;base64,$(base64 DSC_0251.JPG)"

Generic OSX/Linux

As Shell Function

@base64() {
  if [[ "${OSTYPE}" = darwin* ]]; then
    # OSX
    if [ -t 0 ]; then
      base64 "$@"
    else
      cat /dev/stdin | base64 "$@"
    fi
  else
    # Linux
    if [ -t 0 ]; then
      base64 -w 0 "$@"
    else
      cat /dev/stdin | base64 -w 0 "$@"
    fi
  fi
}

# Usage
@base64 DSC_0251.JPG
cat DSC_0251.JPG | @base64

As Shell Script

Create base64.sh file with following content:

#!/usr/bin/env bash
if [[ "${OSTYPE}" = darwin* ]]; then
  # OSX
  if [ -t 0 ]; then
    base64 "$@"
  else
    cat /dev/stdin | base64 "$@"
  fi
else
  # Linux
  if [ -t 0 ]; then
    base64 -w 0 "$@"
  else
    cat /dev/stdin | base64 -w 0 "$@"
  fi
fi

Make it executable:

chmod a+x base64.sh

Usage:

./base64.sh DSC_0251.JPG
cat DSC_0251.JPG | ./base64.sh

Decode

Get you readable data back:

base64 -d DSC_0251.base64 > DSC_0251.JPG 

--

UPDATE - On MacOS Monterey or the latest

# Instead of base64 DSC_0251.JPG
base64 -i DSC_0251.JPG

If you want to save the output in a file,

# Instead of base64 -w 0 DSC_0251.JPG > DSC_0251.JPG.base64
base64 -i DSC_0251.JPG -o DSC_0251.JPG.base64
BadPiggie
  • 5,471
  • 1
  • 14
  • 28
Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
41

There is a Linux command for that: base64

base64 DSC_0251.JPG >DSC_0251.b64

To assign result to variable use

test=`base64 DSC_0251.JPG`
David Jashi
  • 4,490
  • 1
  • 21
  • 26
4

If you need input from termial, try this

lc=`echo -n "xxx_${yyy}_iOS" |  base64`

-n option will not input "\n" character to base64 command.

Victor Choy
  • 4,006
  • 28
  • 35
3

Base 64 for html:

file="DSC_0251.JPG"
type=$(identify -format "%m" "$file" | tr '[A-Z]' '[a-z]')
echo "data:image/$type;base64,$(base64 -w 0 "$file")"
Andrey Izman
  • 1,807
  • 1
  • 24
  • 27
1

To base64 it and put it in your clipboard:

file="test.docx"
base64 -w 0 $file  | xclip -selection clipboard
DavidBu
  • 478
  • 4
  • 6
0

Please be very cautious when using echo (as many answers here), because it will add a newline character at the end, distorting your encoded string (leading to e.g. incorrect passwords) due to these ominous extra encoded characters: Cg== added at the end of the encoded string:

For example, if we have this string to encode:

$ MINIO_SECRET_KEY=VsarGnNADHGv

With `printf' it will look like this (correct):

$ AWS_SECRET_ACCESS_KEY="$(printf $MINIO_SECRET_KEY | base64)" && echo $AWS_SECRET_ACCESS_KEY
VnNhckduTkFESEd2

... but with echo like this (incorrect):

$ AWS_SECRET_ACCESS_KEY="$(echo $MINIO_SECRET_KEY | base64)" && echo $AWS_SECRET_ACCESS_KEY
VnNhckduTkFESEd2Cg==
mirekphd
  • 4,799
  • 3
  • 38
  • 59
0

On macOS Monterey, you would use:

base64 -i image.jpg
Amir Hajiha
  • 836
  • 8
  • 20
  • Please make more obvious what additional insight you contribute beyond existing and better explained answers. I.e. what is the difference of your solution and why is it a relevant advantage over what was already given? – Yunnosch Mar 29 '23 at 06:26
  • I tried all of the other solutions in this post myself and none would work as it now needs a -i switch in order to specify the file name to be used. – Amir Hajiha Mar 30 '23 at 10:01
  • Interesting, please [edit] to improve your answer post with that explanation. Make sure to explain what "now" means. What changed, when, how, why? – Yunnosch Mar 30 '23 at 11:35