2
\$\begingroup\$

I'm writing a helper script that I wish to be able to share with my co-workers. We all work using macOS Mojave, but all have their own shell configurations. For example, I actually use ZSH and bash 5.0.

There are often times where I am working with data that is output from our nightly testing that runs on a remote cluster.

I could just run the tests locally, but that would take up most of my day. So I wrote a script that fetches the data from the remote server.

Recently, a few coworkers have expressed interest in using this script. So I was hoping to get a quick review of it, before I sent it off to them.

My goal is to have a reliable, well-written script that could be easy to debug for my coworkers. Also it being able to work on any macOS would be awesome.

#!/usr/bin/env bash

NORMAL='\033[0m'
RED='\033[1;31m'
GREEN='\033[0;32m'
BLUE='\033[1;34m'
MAGENTA='\033[1;4;35m'
YELLOW='\033[1;33m'

dry_run=0
lookback=1
folder=""
BISON=${BISON_DIR:-$HOME/Documents/projects/bison}

function foldernames () {
    (printf "Calvert_Cliffs-1_PROTOTYPE   IFA_636                          RIA_CABRI_REP_Na4\n"
     printf "FUMEXII_Regate               IFA_677                           RIA_NSRR_FK\n"
     printf "HBEP                         LOCA_ANL_cladding_burst_tests    Riso_AN2\n"
     printf "HbepR1                       LOCA_Hardy_cladding_test         Riso_AN3\n"
     printf "IFA_431                      LOCA_IFA_650                      Riso_AN4\n"
     printf "IFA_432                      LOCA_MT4_MT6A                     Riso_AN8\n"
     printf "IFA_513                      LOCA_ORNL_cladding_burst_tests       Riso_GE7_ZX115\n"
     printf "IFA_515_RodA1                LOCA_PUZRY_cladding_burst_tests   Riso_GEm_STR013\n"
     printf "IFA_519                      LOCA_REBEKA_cladding_burst_tests  Riso_II3\n"
     printf "IFA_534                      OSIRIS_H09                        Riso_II5\n"
     printf "IFA_535                      OSIRIS_J12                        Super_Ramp\n"
     printf "IFA_562                      RE_Ginna_Rodlets                  Tribulation\n"
     printf "IFA_597_3                    RIA_CABRI_REP_Na                  US_PWR_16_x_16\n") | column -t
}

function usage () {
    printf "Usage: bisfetch [-n] [-l num] [-f folder] [folder(s) ...]\n"
    printf "  -h \t - show this message\n"
    printf "  -n \t - perform a dry-run\n"
    printf "  -l \t - Integer value; Look back a previous run; Defaults to 1 (most-recent)\n"
    printf "  -f \t - Folder of interest; The flag is optional but a folder is required."
    printf "\n"
    printf "Folder of interest required! Possible folder names include:\n\n"
    foldernames
    exit 1
}

while getopts ":hnl:f:" flag; do
    case "$flag" in
        n ) dry_run=1
            ;;
        l ) lookback=${OPTARG}
            ;;
        h ) usage
            ;;
        f ) folder="${OPTARG}"
            ;;
        : ) echo "Invalid options: $OPTARG requires an argurment" 1>&2
            exit 1
            ;;
        \? ) echo "Usage: bisfetch [-n] [-l num] [-f folder] [folder(s) ...]"
             exit 1
             ;;
    esac
done

shift $((OPTIND-1))

# Check to ensure folder is specified
if [ -z "$folder" ] && [ -z "$1" ]; then
    printf "%b\n\n" "${RED}You must specify a folder of interest:${NORMAL}"
    foldernames
    exit 1
fi

# If no -f flag then assign folder to first ARG
[ -n "$1" ] && folder="$1"

# Find all *_out.csv files on Falcon1 for specific folder
# This is some bash-fu, but bassically we want to find the most recently
# modified folder of the type 'bison_XXXXXXXX'
# We then want to find all the *_out.csv files inside the folder specified at the
# command-line within the 'bison_XXXXXXXX' folder.
mapfile -t files < <(ssh falcon1 -qn 'newest=$(find /projects/bison/git/* -mindepth 0 -maxdepth 0 -type d -regex ".*/bison_[0-9]+" -printf "%T@\t%f\n" | ' \
                         'sort -t\t -r -nk1,5 | ' \
                         'sed -n '"$lookback"'p | ' \
                         'cut -f2-); ' \
                         'find /projects/bison/git/$newest/assessment/LWR/validation/'"$folder"'/* -type f -name "*_out.csv" -not -path "*/doc/*" -printf "%p\n" 2>/dev/null')

# Modify remote paths to fit for local paths
mapfile -t local_paths < <(for i in "${files[@]}"; do
                               echo "$i" |
                                   sed -E "s|/projects/bison/git/bison_[0-9]{8}|$BISON|g"; done)

# If ssh returned no results then error out.
if [[ -z "${files[0]}" ]]; then
    printf "%b\n\n" "${RED}ERROR: Folder '$folder' Not Found!${NORMAL}"
    printf "%b\n" "${YELLOW}Possible Folder Names Include:${NORMAL}"
    foldernames
    exit 1
else
    printf "\n\t📁 Inspecting Nightly Folder %b for Assessment %b:\n" \
           "${MAGENTA}${files[0]:20:14}${NORMAL}" "${MAGENTA}$folder${NORMAL}"
fi

for ((i=0; i<${#files[@]}; i++)); do
    if [[ $dry_run == 0 ]]; then
        printf "\t╭─ %b %s\n" "${BLUE}Remote =>${NORMAL}" "${files[i]}"
        printf "\t├─ %b %s\n" "${YELLOW}Local  =>${NORMAL}" "${local_paths[i]}"

        printf "\t╰─ Fetching Remote File...\r"
        if scp -qp falcon1:"${files[i]}" "${local_paths[i]}" 2>/dev/null; then
            printf "\t%b\n\n" "╰─ Fetching Remote File… ${GREEN}Successful!${NORMAL}"
        else
            printf "\t%b\n\n" "╰─ Fetching Remote File… ${RED}Error!{$NORMAL}"
        fi
    else
        printf "\t╭─ %b %s\n" "${BLUE}Remote =>${NORMAL}" "${files[i]}"
        printf "\t╰─ %b %s\n\n" "${YELLOW}Local  =>${NORMAL}" "${local_paths[i]}"
    fi
done
```
\$\endgroup\$

0

Browse other questions tagged or ask your own question.