Spyke

Syndicated from the fediverse. Read and engage on the original instance.

View original on lemmy.world
shellscripting·Shell ScriptingbyWillieShen

My bash functions for compression, file name handling, delimiters matching, LaTeX, multimedia processing etc. in .bashrc

__pv() {
  if command -v pv >/dev/null 2>&1; then
    pv
  else
    cat
  fi
}

compress_single() {
  local msg='Usage: compress_single [-h|--help]
compress_single [-t|--tar] [-n|--no-tar] [-p|--pad PAD] COMMAND SOURCE [TARGET]
If TARGET is not provided and PAD is provided, SOURCE concatenating PAD is used.
No tar is used by default.'
  local tar=0
  local pad=''
  local target=''
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -h | --help)
        echo "$msg"
        return 0
        ;;
      -t | --tar)
        tar=1
        shift
        ;;
      -n | --no-tar)
        tar=0
        shift
        ;;
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        pad="$2"
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  if [ "$#" -eq 3 ]; then
    target="$3"
  elif [ "$#" -eq 2 ] && [ -n "$pad" ]; then
    target="${2}${pad}"
  else
    echo "$msg" >&2
    return 1
  fi
  if [ "$tar" -eq 1 ]; then
    (
      set -o pipefail
      tar -cf - "$2" | __pv | $1 | __pv >"$target"
    )
  else
    (
      set -o pipefail
      $1 "$2" | __pv >"$target"
    )
  fi
}

split_file() {
  local bytes
  if [ -n "${SPLIT_SIZE:-}" ]; then
    bytes="$SPLIT_SIZE"
  else
    bytes="4000M"
  fi
  split -b "$bytes" -d -a 3 "$1" "$1.part."
}

compress_split() {
  # shellcheck disable=2016
  local msg='Usage: compress_split [-h|--help]
compress_split [-t|--tar] [-n|--no-tar] [-p|--pad PAD] [-b BYTES|--bytes BYTES] COMMAND SOURCE [TARGET]
If TARGET is not provided and PAD is provided, SOURCE concatenating PAD is used.
No tar is used by default.
If BYTES is not provided, $SPLIT_SIZE is used if set and 4000M is used otherwise.'
  local bytes
  local pad=''
  local target=''
  if [ -n "${SPLIT_SIZE:-}" ]; then
    bytes="$SPLIT_SIZE"
  else
    bytes="4000M"
  fi
  local tar=0
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -h | --help)
        echo "$msg"
        return 0
        ;;
      -t | --tar)
        tar=1
        shift
        ;;
      -n | --no-tar)
        tar=0
        shift
        ;;
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        pad="$2"
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        bytes="$2"
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  if [ "$#" -eq 3 ]; then
    target="$3"
  elif [ "$#" -eq 2 ] && [ -n "$pad" ]; then
    target="${2}${pad}"
  else
    echo "$msg" >&2
    return 1
  fi
  if [ "$tar" -eq 1 ]; then
    (
      set -o pipefail
      tar -cf - "$2" | __pv | $1 | __pv | split -b "$bytes" -d -a 3 - "$target.part."
    )
  else
    (
      set -o pipefail
      $1 "$2" | __pv | split -b "$bytes" -d -a 3 - "$target.part."
    )
  fi
}

bz2_single() {
  compress_single --tar --pad '.tar.bz2' 'bzip2 -9' "$@"
}

gz_single() {
  compress_single --tar --pad '.tar.gz' 'gzip -9' "$@"
}

xz_single() {
  compress_single --tar --pad '.tar.xz' 'xz -9' "$@"
}

tar_single() {
  compress_single --no-tar --pad '.tar' 'tar -cf -' "$@"
}

zip_single() {
  compress_single --no-tar --pad '.zip' 'zip -r -9 -' "$@"
}

bz2_split() {
  compress_split --tar --pad '.tar.bz2' 'bzip2 -9' "$@"
}

gz_split() {
  compress_split --tar --pad '.tar.gz' 'gzip -9' "$@"
}

xz_split() {
  compress_split --tar --pad '.tar.xz' 'xz -9' "$@"
}

tar_split() {
  compress_split --no-tar --pad '.tar' 'tar -cf -' "$@"
}

zip_split() {
  compress_split --no-tar --pad '.zip' 'zip -r -9 -' "$@"
}

bz2_single_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_single --tar --pad '.tar.bz2' 'bzip2 -9' "$f" "$@" && rm -- "$f"
    done
  )
}

gz_single_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_single --tar --pad '.tar.gz' 'gzip -9' "$f" "$@" && rm -- "$f"
    done
  )
}

xz_single_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_single --tar --pad '.tar.xz' 'xz -9' "$f" "$@" && rm -- "$f"
    done
  )
}

tar_single_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_single --no-tar --pad '.tar' 'tar -cf -' "$f" "$@" && rm -- "$f"
    done
  )
}

zip_single_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_single --no-tar --pad '.zip' 'zip -r -9 -' "$f" "$@" && rm -- "$f"
    done
  )
}

bz2_split_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_split --tar --pad '.tar.bz2' 'bzip2 -9' "$f" "$@" && rm -- "$f"
    done
  )
}

gz_split_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_split --tar --pad '.tar.gz' 'gzip -9' "$f" "$@" && rm -- "$f"
    done
  )
}

xz_split_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_split --tar --pad '.tar.xz' 'xz -9' "$f" "$@" && rm -- "$f"
    done
  )
}

tar_split_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_split --no-tar --pad '.tar' 'tar -cf -' "$f" "$@" && rm -- "$f"
    done
  )
}

zip_split_all() {
  (
    shopt -s nullglob
    for f in *; do
      compress_split --no-tar --pad '.zip' 'zip -r -9 -' "$f" "$@" && rm -- "$f"
    done
  )
}

extract_all_and() {
  local erar=0
  local ezip=0
  local etargz=0
  local etgz=0
  local egz=0
  local etarbz2=0
  local etbz2=0
  local ebz2=0
  local etarxz=0
  local etxz=0
  local exz=0
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --erar | --exclude-rar)
        erar=1
        shift
        ;;
      --ezip | --exclude-zip)
        ezip=1
        shift
        ;;
      --etargz | --exclude-targz)
        etargz=1
        shift
        ;;
      --etgz | --exclude-tgz)
        etgz=1
        shift
        ;;
      --egz | --exclude-gz)
        egz=1
        shift
        ;;
      --etarbz2 | --exclude-tarbz2)
        etarbz2=1
        shift
        ;;
      --etbz2 | --exclude-tbz2)
        etbz2=1
        shift
        ;;
      --ebz2 | --exclude-bz2)
        ebz2=1
        shift
        ;;
      --etarxz | --exclude-tarxz)
        etarxz=1
        shift
        ;;
      --etxz | --exclude-txz)
        etxz=1
        shift
        ;;
      --exz | --exclude-xz)
        exz=1
        shift
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  [ "$#" -lt 2 ] && return 1
  (
    shopt -s globstar nullglob
    for f in "$1" "$1"/**/*; do
      [[ -f $f ]] || continue
      local file=${f##*/}
      local dir=${f%/*}
      [[ $dir == "$f" ]] && dir=.
      local un=''
      local -a cmd=()
      case $file in
        *.rar)
          [ "$erar" -eq 1 ] && continue
          un=${file%.rar}
          cmd=(unrar x)
          ;;
        *.zip)
          [ "$ezip" -eq 1 ] && continue
          un=${file%.zip}
          cmd=(unzip)
          ;;
        *.tar.gz)
          [ "$etargz" -eq 1 ] && continue
          un=${file%.tar.gz}
          cmd=(tar -xzf)
          ;;
        *.tgz)
          [ "$etgz" -eq 1 ] && continue
          un=${file%.tgz}
          cmd=(tar -xzf)
          ;;
        *.gz)
          [ "$egz" -eq 1 ] && continue
          un=${file%.gz}
          cmd=(gzip -d)
          ;;
        *.tar.bz2)
          [ "$etarbz2" -eq 1 ] && continue
          un=${file%.tar.bz2}
          cmd=(tar -xjf)
          ;;
        *.tbz2)
          [ "$etbz2" -eq 1 ] && continue
          un=${file%.tbz2}
          cmd=(tar -xjf)
          ;;
        *.bz2)
          [ "$ebz2" -eq 1 ] && continue
          un=${file%.bz2}
          cmd=(bzip2 -d)
          ;;
        *.tar.xz)
          [ "$etarxz" -eq 1 ] && continue
          un=${file%.tar.xz}
          cmd=(tar -xJf)
          ;;
        *.txz)
          [ "$etxz" -eq 1 ] && continue
          un=${file%.txz}
          cmd=(tar -xJf)
          ;;
        *.xz)
          [ "$exz" -eq 1 ] && continue
          un=${file%.xz}
          cmd=(xz -d)
          ;;
        *)
          continue
          ;;
      esac
      (
        cd "$dir" &&
          "${cmd[@]}" "$file" &&
          rm -- "$file" &&
          "${@:2}" "$un" &&
          rm -rf -- "$un"
      )
    done
  )
}

extract_all() {
  extract_all_and "$@" false
}

extract_all_and_bz2() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" bz2_single "${args[@]}"
}

extract_all_and_gz() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" gz_single "${args[@]}"
}

extract_all_and_xz() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" xz_single "${args[@]}"
}

extract_all_and_tar() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" tar_single "${args[@]}"
}

extract_all_and_zip() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" zip_single "${args[@]}"
}

extract_all_and_bz2_split() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" bz2_split "${args[@]}"
}

extract_all_and_gz_split() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" gz_split "${args[@]}"
}

extract_all_and_xz_split() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" xz_split "${args[@]}"
}

extract_all_and_tar_split() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" tar_split "${args[@]}"
}

extract_all_and_zip_split() {
  local -a args=()
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          return 1
        fi
        args+=("$1" "$2")
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  extract_all_and "$@" zip_split "${args[@]}"
}

remove_extension() {
  sed -E 's/^(.+)\.[^.]+$/\1/'
}

get_extension() {
  sed -E '/^\.?[^.]+$/d; s/^.+\.([^.]*)$/\1/'
}

ls_extension() {
  find . -type f | sed -n 's/.*\(\.[^.\/]*\)$/\1/p' | sort -u
}

ffmpeg_av1_opus() {
  if [ "$#" -lt 4 ]; then
    return
  fi
  local new="${5:-"$(echo "$4" | remove_extension)_ffmpeg_av1_$1_$2_opus_$3.mkv"}"
  if ! ffmpeg -n -i "$4" -c:v libsvtav1 -preset "$1" -crf "$2" -c:a libopus -vbr:a 1 -b:a "$3" "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

ffmpeg_av1_lossless_flac() {
  if [ "$#" -eq 0 ]; then
    return
  fi
  local new="${2:-"$(echo "$1" | remove_extension)_ffmpeg_av1_lossless_flac.mkv"}"
  if ! ffmpeg -n -i "$1" -c:v libsvtav1 -svtav1-params lossless=1 -preset -2 -c:a flac "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

ffmpeg_opus() {
  if [ "$#" -lt 2 ]; then
    return
  fi
  local new="${3:-"$(echo "$2" | remove_extension)_ffmpeg_opus_$1.opus"}"
  if ! ffmpeg -n -i "$2" -c:a libopus -vbr:a 1 -b:a "$1" "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

ffmpeg_flac() {
  if [ "$#" -eq 0 ]; then
    return
  fi
  local new="${2:-"$(echo "$1" | remove_extension)_ffmpeg_flac.flac"}"
  if ! ffmpeg -n -i "$1" -c:a flac "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

ffmpeg_segment() {
  if [ "$#" -lt 2 ]; then
    return
  fi
  ffmpeg -n -i "$2" -c copy -map 0 -segment_time "$1" -f segment -reset_timestamps 1 "${3:-"$(echo "$2" | remove_extension)_ffmpeg_%04d.$(echo "$2" | get_extension)"}"
}

ffmpeg_concat_auto() {
  local -a files=()
  if [ "$#" -eq 0 ]; then
    for f in *; do
      test -f "$f" && files+=("$f")
    done
  else
    files=("$@")
  fi
  ffmpeg -n -f concat -safe 0 -i <(printf "file '$PWD/%s'\n" "${files[@]}") -c copy "$(echo "${files[0]}" | remove_extension | sed -E 's/_ffmpeg_[0-9]+$//').$(echo "${files[0]}" | get_extension)"
}

ffmpeg_concat() {
  if [ "$#" -lt 2 ]; then
    return
  fi
  ffmpeg -n -f concat -safe 0 -i <(printf "file '$PWD/%s'\n" "${@:2}") -c copy "$1"
}

echo_non_ffmpeg() {
  while IFS= read -r -d '' f; do
    case "$f" in
      *ffmpeg_*) ;;
      *)
        echo "$f"
        ;;
    esac
  done < <(find . -type f -print0)
}

remove_non_ffmpeg() {
  while IFS= read -r -d '' f; do
    case "$f" in
      *ffmpeg_*) ;;
      *)
        rm -f -- "$f"
        ;;
    esac
  done < <(find . -type f -print0)
}

echo_ffmpeg() {
  while IFS= read -r -d '' f; do
    case "$f" in
      *ffmpeg_*)
        echo "$f"
        ;;
      *) ;;
    esac
  done < <(find . -type f -print0)
}

remove_ffmpeg() {
  while IFS= read -r -d '' f; do
    case "$f" in
      *ffmpeg_*)
        rm -f -- "$f"
        ;;
      *) ;;
    esac
  done < <(find . -type f -print0)
}

jxl_lossy() {
  if [ "$#" -lt 2 ]; then
    return
  fi
  local new="${3:-"$(echo "$2" | remove_extension).jxl"}"
  if ! cjxl -j 0 -e 10 -d "$1" "$2" "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

jxl_lossless() {
  if [ "$#" -eq 0 ]; then
    return
  fi
  local new="${2:-"$(echo "$1" | remove_extension).jxl"}"
  if ! cjxl -j 1 -e 10 -d 0 "$1" "$new"; then
    rm -f -- "$new"
    return 1
  fi
}

multimedia_convert() {
  (
    shopt -s globstar nullglob
    for f in **/*; do
      [[ -f $f ]] || continue
      local file=${f##*/}
      local dir=${f%/*}
      [[ $dir == "$f" ]] && dir=.
      case ${file,,} in
        *_ffmpeg_av1_*_*_opus_*.mkv | *_ffmpeg_av1_lossless_flac*.mkv)
          continue
          ;;
        *.ico | *.flac | *.gif | *.opus)
          local ext="${file##*.}"
          ext="${ext,,}"
          if [[ ${file##*.} != "$ext" ]]; then
            if [[ -e "${f%.*}.${ext}" ]]; then
              printf 'Skipping: output exists: %s\n' "$f" >&2
              continue
            fi
            mv -- "$f" "${f%.*}.${ext}"
          fi
          ;;
        *.jpg | *.jpeg | *.png)
          local jxl="${file%.*}.jxl"
          if [[ -e "$dir/$jxl" ]]; then
            printf 'Skipping: output exists: %s\n' "$f" >&2
            continue
          fi
          (
            cd "$dir" &&
              jxl_lossy 1 "./$file" "./$jxl" &&
              rm -- "$file"
          )
          ;;
        *.avif | *.bmp | *.heic | *.heif | *.jp2 | *.tif | *.webp)
          local png="${file%.*}.png"
          if [[ -e "$dir/$png" ]]; then
            printf 'Skipping: intermediate png exists: %s\n' "$f" >&2
            continue
          fi
          local jxl="${file%.*}.jxl"
          if [[ -e "$dir/$jxl" ]]; then
            printf 'Skipping: output exists: %s\n' "$f" >&2
            continue
          fi
          (
            if cd "$dir"; then
              magick "./$file" "./$png" &&
                jxl_lossy 1 "./$png" "./$jxl" &&
                rm -- "$file"
              rm -f -- "$png"
            fi
          )
          ;;
        *.3gp | *.mov | *.vob | *.wmv)
          (
            cd "$dir" &&
              ffmpeg_av1_opus 4 40 24k "./$file" &&
              rm -- "$file"
          )
          ;;
        *.avi | *.mkv | *.mp4 | *.mts | *.webm)
          (
            cd "$dir" &&
              ffmpeg_av1_opus 4 32 72k "./$file" &&
              rm -- "$file"
          )
          ;;
        *.aac | *.mp3 | *.m4a | *.ogg)
          (
            cd "$dir" &&
              ffmpeg_opus 96k "./$file" &&
              rm -- "$file"
          )
          ;;
        *.wav)
          (
            cd "$dir" &&
              ffmpeg_flac "./$file" &&
              rm -- "$file"
          )
          ;;
        *)
          continue
          ;;
      esac
    done
  )
}

clean_file() {
  if [ $# -ne 0 ]; then
    files=("$@")
  else
    files=(*)
  fi
  for f in "${files[@]}"; do
    test -f "$f" && perl -i -pe 's/\x{FEFF}//g; s/\x{200B}//g; s/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]//g' -- "$f"
  done
}

latexmkc() {
  if command -v latexmk >/dev/null 2>&1; then
    latexmk -c
  else
    rm -f -- *.acn *.acr *.alg *.aux *.bbl *.blg *.fdb_latexmk *.fls *.glg *.glo *.gls *.idx *.ilg *.ind *.ist *.lof *.log *.lot *.maf *.mp *.mtc *.mtc1 *.nav *.nlo *.out *.pdfsync *.snm *.tmp *.toc *.top *.tui *.vrb
  fi
}

latexmkC() {
  if command -v latexmk >/dev/null 2>&1; then
    latexmk -C
  else
    latexmkc
    rm -f -- *.dvi *.hnt *.pdf *.ps *.synctex *.synctex.gz
  fi
}

latexci() {
  # shellcheck disable=2016
  local msg='latexci [-h|--help] [-m|--latexmk] [-n|--no-latexmk] [-o|--auto-latexmk] [-r|--reproducible] [-s|--no-reproducible] [-t|--auto-reproducible] [-l|--log log_file] [-c|--clean] [-d|--no-clean] [-e|--engine-times engine-times] engine [files]
--latexmk (default): Use latexmk -"$engine".
--no-latexmk: Use "$engine".
--auto-latexmk: Prefer latexmk -"$engine" and fallback to "$engine".
--reproducible (default): Compile reproducibly.
--no-reproducible: Compile normally.
--auto-reproducible: Prefer to compile reproducibly and fallback to compile normally.
--clean: Clean auxiliary files of each file after successful compilation and remove latexci_${engine}_*_log.txt if the whole run succeeds.
engine-times (default: 2): times to run "$engine" when not using latexmk.
log_file (default: latexci_${engine}_$(date +%s)_log.txt): name of log file. It is only used when there are warnings or errors. If file of the same name has existed, it will be deleted.
files (default: all **/*.tex): LaTeX files to compile.'
  # mk (latexmk), rp (reproducible): 0 auto, 1 must, 2 no
  local mk=1
  local rp=1
  local times=2
  local clean=1
  local log=''
  local -a args=()
  local -a files=()
  while [ $# -gt 0 ]; do
    case "$1" in
      -h | --help)
        echo "$msg"
        return 0
        ;;
      -m | --latexmk)
        mk=1
        shift
        ;;
      -n | --no-latexmk)
        mk=2
        shift
        ;;
      -o | --auto-latexmk)
        mk=0
        shift
        ;;
      -r | --reproducible)
        rp=1
        shift
        ;;
      -s | --no-reproducible)
        rp=2
        shift
        ;;
      -t | --auto-reproducible)
        rp=0
        shift
        ;;
      -l | --log)
        log="$2"
        shift 2
        ;;
      -e | --engine-times)
        if [[ ! $2 =~ ^[0-9]+$ ]] || (($2 < 1)); then
          echo "latexci error: engine-times must be a positive integer." >&2
          return 1
        fi
        times="$2"
        shift 2
        ;;
      -c | --clean)
        clean=1
        shift
        ;;
      -d | --no-clean)
        clean=0
        shift
        ;;
      --)
        shift
        args+=("$@")
        break
        ;;
      *)
        args+=("$1")
        shift
        ;;
    esac
  done
  local engine
  if [ "${#args[@]}" -eq 0 ]; then
    echo 'latexci error: engine required.' >&2
    return 1
  else
    engine="${args[0]}"
  fi
  local cwd
  cwd="$(pwd)"
  if [ "${#args[@]}" -ne 1 ]; then
    files=("${args[@]:1}")
  else
    mapfile -d '' -t files < <(
      find "$cwd" -type f -name '*.tex' -print0
    )
  fi
  if [ "${#files[@]}" -eq 0 ]; then
    echo "latexci warning: no .tex file found." >&2
    return 0
  fi
  [ -z "$log" ] && log="latexci_${engine}_$(date +%s)_log.txt"
  rm -f -- "$log"
  for f in "${files[@]}"; do
    local dir
    dir="$(dirname "$f")"
    if ! cd "$dir"; then
      echo "$f: can't cd $dir" >>"$cwd/$log"
      continue
    fi
    local file
    file="$(basename "$f")"
    local -a env_args=()
    local epoch=''
    if [ "$rp" -eq 1 ]; then
      epoch=$(command -v git >/dev/null 2>&1 && git log -1 --format=%ct -- "$file" 2>/dev/null)
      if [ -n "$epoch" ]; then
        env_args=(SOURCE_DATE_EPOCH="$epoch")
      else
        echo "$f: git log failed for and reproducible required" >>"$cwd/$log"
      fi
    elif [ "$rp" -eq 0 ]; then
      epoch=$(command -v git >/dev/null 2>&1 && git log -1 --format=%ct -- "$file" 2>/dev/null)
      if [ -n "$epoch" ]; then
        env_args=(SOURCE_DATE_EPOCH="$epoch")
      fi
    fi
    if [ "$mk" -ne 2 ] && command -v latexmk >/dev/null 2>&1; then
      if env "${env_args[@]}" latexmk -"$engine" -latexoption='-interaction=nonstopmode -halt-on-error' "$file"; then
        [ "$clean" -eq 1 ] && latexmkc
      else
        echo "$f: latexmk $engine failed" >>"$cwd/$log"
      fi
    elif [ "$mk" -ne 1 ] && command -v "$engine" >/dev/null 2>&1; then
      local fail=0
      local et="$times"
      while ((et > 0)); do
        if ! env "${env_args[@]}" "$engine" -interaction=nonstopmode -halt-on-error "$file"; then
          echo "$f: $engine failed" >>"$cwd/$log"
          fail=1
          break
        fi
        ((et--))
      done
      if [ "$fail" -eq 0 ]; then
        [ "$clean" -eq 1 ] && latexmkc
      fi
    else
      echo "$f: all allowed methods not executable" >>"$cwd/$log"
    fi
  done
  if [ "$mk" -eq 0 ] && ! command -v latexmk >/dev/null 2>&1; then
    echo "latexci warning: latexmk not executable, $engine used" >&2
  fi
  if [ -f "$cwd/$log" ]; then
    {
      echo "latexci log"
      echo "$cwd"
      date -uIs
    } >>"$cwd/$log"
    cat "$cwd/$log" >&2
    echo "latexci warning: failures logged to $cwd/${log}." >&2
    # shellcheck disable=2164
    cd "$cwd"
    return 1
  else
    [ "$clean" -eq 1 ] && rm -f -- "$cwd/latexci_${engine}"_*_log.txt
    # shellcheck disable=2164
    cd "$cwd"
  fi
}

xelatexci() {
  latexci xelatex "$@"
}

lualatexci() {
  latexci lualatex "$@"
}

match_round() {
  awk '{ n = gsub(/\(/, "("); m = gsub(/\)/, ")"); balance += n - m; printf "%2d %5d %s\n", balance, NR, $0
}' "$1"
}

match_square() {
  awk '{ n = gsub(/\[/, "["); m = gsub(/\]/, "]"); balance += n - m; printf "%2d %5d %s\n", balance, NR, $0
}' "$1"
}

match_curly() {
  awk '{ n = gsub(/\{/, "{"); m = gsub(/\}/, "}"); balance += n - m; printf "%2d %5d %s\n", balance, NR, $0
}' "$1"
}
View original on lemmy.world
6

No replies yet

No comments on the original post yet.
My bash functions for compression, file name handling, delimiters matching, LaTeX, multimedia processing etc. in .bashrc | Spyke