How to Generate QR Codes in Bash

How to Generate QR Codes in Bash

How to Generate QR Codes in Bash

I needed a fast way to generate QR codes for a stack of Wi-Fi passwords and product links I was printing onto labels for a small event I helped organize. Opening a browser-based QR generator for each one would’ve been painfully slow, so I put together a small Bash script around qrencode, and it turned a half-hour chore into a batch job that finished in seconds. Here’s exactly how I built it.

Why Generate QR Codes from Bash

QR code generation seems like a “GUI tool” kind of task, but doing it from the command line has real advantages:

The Tool Behind It: qrencode

The most widely used command-line QR code generator is qrencode, part of the libqrencode project.

Install on Debian/Ubuntu:

sudo apt update
sudo apt install qrencode

On Fedora:

sudo dnf install qrencode

On macOS (via Homebrew):

brew install qrencode

The Simplest QR Code Generator

qrencode -o qrcode.png "https://example.com"

This generates a PNG file named qrcode.png encoding the given URL. That’s the entire core operation — everything else is about making it flexible and reusable.

Displaying a QR Code Directly in the Terminal

For a quick preview without opening an image viewer, qrencode can render directly as ASCII art:

qrencode -t ANSIUTF8 "https://example.com"

This is genuinely useful when SSH’d into a remote server and you want to scan something (like a two-factor auth secret) without transferring a file.

A Basic Bash Script Wrapper

#!/bin/bash

set -euo pipefail

usage() {
    echo "Usage: $0 <text_or_url> <output_file.png>"
    exit 1
}

if [ "$#" -ne 2 ]; then
    usage
fi

content="$1"
output_file="$2"

qrencode -o "$output_file" -s 10 -l H "$content"

echo "QR code saved to $output_file"

How This Works Internally

Batch-Generating QR Codes from a List

Here’s a script that reads a list of items from a text file (one per line) and generates a QR code for each:

#!/bin/bash

set -euo pipefail

input_list="$1"
output_dir="qrcodes"

mkdir -p "$output_dir"

counter=1
while IFS= read -r line; do
    [ -z "$line" ] && continue
    filename=$(printf "%s/qr_%03d.png" "$output_dir" "$counter")
    qrencode -o "$filename" -s 8 -l H "$line"
    echo "Generated: $filename for '$line'"
    ((counter++))
done < "$input_list"

echo "All QR codes generated in '$output_dir/'"

Breaking It Down

Generating QR Codes from a CSV File (Name + URL Pairs)

A more structured, real-world version reads name/value pairs from a CSV and names each output file after the record:

#!/bin/bash

set -euo pipefail

csv_file="$1"
output_dir="qrcodes"

mkdir -p "$output_dir"

while IFS=',' read -r name url; do
    [ -z "$name" ] && continue
    safe_name=$(echo "$name" | tr ' ' '_' | tr -cd 'A-Za-z0-9_-')
    qrencode -o "$output_dir/${safe_name}.png" -s 8 -l H "$url"
    echo "Generated QR for $name -> $output_dir/${safe_name}.png"
done < "$csv_file"

Given a CSV like:

Product A,https://example.com/product-a
Product B,https://example.com/product-b

This produces Product_A.png and Product_B.png, each encoding the corresponding URL.

Generating a Wi-Fi QR Code

QR codes can also encode structured Wi-Fi connection data, so scanning the code automatically connects a phone to a network:

#!/bin/bash

ssid="MyNetwork"
password="SuperSecret123"
encryption="WPA"  # WPA, WEP, or nopass

qrencode -o wifi_qr.png -s 10 -l H "WIFI:T:${encryption};S:${ssid};P:${password};;"

The format WIFI:T:<type>;S:<ssid>;P:<password>;; is a standard recognized by most modern phone camera apps, letting a scan connect instantly without manually typing the password.

Real-World Use Cases

Automation Example

Here’s a script I use that watches a folder for new CSV exports (e.g., from a spreadsheet tool) and automatically regenerates QR codes whenever the file changes:

#!/bin/bash

set -euo pipefail

csv_file="/data/product_links.csv"
output_dir="/data/qrcodes"
last_hash_file="/tmp/qr_csv_hash"

mkdir -p "$output_dir"

current_hash=$(sha256sum "$csv_file" | awk '{print $1}')
last_hash=$(cat "$last_hash_file" 2>/dev/null || echo "")

if [ "$current_hash" != "$last_hash" ]; then
    while IFS=',' read -r name url; do
        [ -z "$name" ] && continue
        safe_name=$(echo "$name" | tr ' ' '_' | tr -cd 'A-Za-z0-9_-')
        qrencode -o "$output_dir/${safe_name}.png" -s 8 -l H "$url"
    done < "$csv_file"
    echo "$current_hash" > "$last_hash_file"
    echo "QR codes regenerated due to CSV changes."
else
    echo "No changes detected in CSV; skipping regeneration."
fi

This only regenerates QR codes when the source CSV file has actually changed, avoiding unnecessary reprocessing on every cron run.

Best Practices

Security Considerations

Optimization Tips

cat urls.txt | xargs -P 4 -I{} qrencode -o "qr_{}.png" "{}"

(Note: this simplified example needs adjustment for filenames with special characters — sanitize before using in production.)

Troubleshooting Common Issues

Problem: qrencode: command not found. Install it via your package manager and confirm with qrencode --version.

Problem: Generated QR code won’t scan. Increase the error correction level (-l H) and module size (-s), and ensure there’s adequate white space (“quiet zone”) around the code when printed.

Problem: Wi-Fi QR code doesn’t connect automatically. Double-check the exact format string — a missing semicolon or incorrect encryption type (WPA vs WEP vs nopass) will break parsing on the scanning device.

Problem: Special characters in content break the QR encoding. Ensure the string is properly quoted when passed to qrencode, and check the encoding of your input file (UTF-8 is recommended).

Common Mistakes to Avoid

Frequently Asked Questions

Can qrencode generate QR codes for contact cards (vCard)? Yes, format the content as a standard vCard string (BEGIN:VCARD...END:VCARD) and pass it as the content argument, and most scanner apps will recognize it as a contact card.

What’s the maximum amount of data a QR code can hold? Up to about 4,296 alphanumeric characters, though practical scanability drops significantly as content length grows — shorter is generally better.

Can I generate colored QR codes? qrencode itself only generates black-and-white codes; for colored or styled QR codes, you’d need to post-process the output with an image tool like ImageMagick.

Is it possible to generate QR codes without installing anything? Not without a dependency — qrencode (or an equivalent library) is required since QR generation involves nontrivial encoding logic that Bash itself doesn’t provide natively.

Can I embed a logo in the middle of a generated QR code? Not directly through qrencode; you’d generate the QR code with high error correction (-l H) and then overlay a logo image using ImageMagick, since higher error correction tolerates the added obstruction.

Summary

Generating QR codes in Bash is a great example of Bash’s strength as an orchestration layer — the actual encoding logic lives in qrencode, while Bash handles batching, file naming, input parsing, and automation. Starting from a single qrencode -o file.png "text" command, you can build a tool that processes entire CSV files, generates Wi-Fi credentials, and integrates into automated content pipelines, all without ever touching a browser-based generator or exposing sensitive data to a third party.

References

Exit mobile version