Quick Shell Scripting Examples

These quick examples aren’t all practical, but they show examples of what you can do with small shell scripts (make HTTP requests, download files, process JSON, move files, etc.).

This takes a command line argument (a github username) and opens Firefox with that user’s Github avatar. By default, it downloads my avatar. Save as avatar.sh, set the permissions (chmod u+x avatar.sh) and then run with: ./avatar.sh your_github_username

#!/bin/bash

# this is how to create a default value if an argument isn't provided
URL="https://api.github.com/users/${1:-j127}"

# jq is a tools for processing JSON. It might need to be downloaded if
# the script doesn't run.
firefox $(curl -s $URL | jq -r '.avatar_url')

This initializes a project in the current directory with some default files, if they don’t already exist:

#!/bin/bash

# this is the location of the template files
SCRIPT_LOCATION='/home/username/code/project_starter'
TEMPLATE_DIR=templates

# these are the files to copy
FILES=(
    ".editorconfig"
    ".gitignore"
    "Makefile"
    "README.md"
)

# loop over the files and copy them in to the current directory
for F in "${FILES[@]}"; do
    if [[ -e "$F" ]]; then
        echo "$F already exists -- skipping..."
    else
        cp "${SCRIPT_LOCATION}/${TEMPLATE_DIR}/${F}" .
        echo "copied file: ${TEMPLATE_DIR}/${F}"
    fi
done

This next one lists the names of all the dependencies in a package.json file in a readable format. There must be a package.json file in the current directory.

#!/bin/bash

# this also uses a default value if no arg is provided -- the output of the `pwd` command
file="${1:-$PWD}/package.json"

DEPS=$(jq -r '.dependencies | keys | .[]' $file | sort)
DEV_DEPS=$(jq -r '.devDependencies | keys | .[]' $file | sort)

echo 'Dependencies'
echo '------------'
echo "$DEPS"

echo ""
echo 'Dev Dependencies'
echo '----------------'
echo "$DEV_DEPS"

This downloads a random cat picture and prints it in the terminal using ASCII characters. It’s a quick script that doesn’t have error checking and will fail if it’s not a jpg.

#!/bin/bash

# load API key (an environment variable set on the computer)
if [[ -z "${PIXABAY_API_KEY}" ]]; then
    echo 'You need to set a PIXABAY_API_KEY environment variable to run this program.'
    exit 1
fi

# customize your query here or grab one from the arguments
QUERY='cat'

JSON=$(curl -s "https://pixabay.com/api/?q=${QUERY}&key=${PIXABAY_API_KEY}&image_type=photo&orientation=horizontal")

# download image
IMG_URL=$(echo $JSON | jq -r '.hits[0].largeImageURL')
NUM_RESULTS=$(echo $JSON | jq '.totalHits')
# echo "found $NUM_RESULTS images"

IMG_INDEX=$((1 + RANDOM % 20))
# echo "choosing image with index $IMG_INDEX"

JQ_QUERY=".hits[$IMG_INDEX].largeImageURL"

IMG_URL=$(echo $JSON | jq -r $JQ_QUERY)
echo "fetching ${IMG_URL}"

curl -s $IMG_URL | jp2a -
1 Like

If you learn how to use and combine various commands it can really speed up work. Today I was looking for a way to turn multiple Org Mode files into a single, readable HTML file. The filenames are in the format 2019-03-17-Sunday.org, and I wanted them in order of date. I was able to quickly do it like this:

$ cat $(ls -1 | sort | grep org$) | pandoc -f org -t html > output.html

Explanation:

  1. cat – concatenates multiple files to stdout
  2. $() – evaluates the commands inside the parentheses
  3. ls -1 – prints a list of files in one column
  4. | – pipes the output of one command into the next command
  5. sort – sorts the results (by date in this case)
  6. grep org$ – this filters out any files that don’t have org as the last part of the filename (excludes directories and backup files that end with a tilde, like filename.org~)
  7. pandoc -f org -t htmlpandoc is a tool to convert between formats, in this case from (-f) Org Mode to (-t) HTML
  8. > this sends the output to a file named output.html
1 Like