Compare commits
10 commits
f109fbfcc3
...
cf550ef9ca
| Author | SHA1 | Date | |
|---|---|---|---|
| cf550ef9ca | |||
| 312f67789b | |||
| 0b679c4a01 | |||
| 9e399abdf9 | |||
| c0c69f19dd | |||
| 1250e3f248 | |||
| 938c53fd85 | |||
| 6788c3d387 | |||
| f108de6556 | |||
| e87dc7f471 |
4 changed files with 166 additions and 66 deletions
37
README.org
37
README.org
|
|
@ -6,13 +6,15 @@
|
||||||
| [[#ffconv][ffconv]] | Convert multiple media files from one format to another |
|
| [[#ffconv][ffconv]] | Convert multiple media files from one format to another |
|
||||||
| [[#ffcut][ffcut]] | Extract a part of a media file |
|
| [[#ffcut][ffcut]] | Extract a part of a media file |
|
||||||
|
|
||||||
|
All are created with the [[https://github.com/Deleh/sf][sf]] script framework.
|
||||||
|
|
||||||
** Dependencies
|
** Dependencies
|
||||||
|
|
||||||
- [[https://ffmpeg.org/][FFmpeg]]
|
- [[https://ffmpeg.org/][FFmpeg]]
|
||||||
|
|
||||||
** Installation
|
** Installation
|
||||||
|
|
||||||
Grab a script and execute it.
|
Grab a script and execute it.
|
||||||
|
|
||||||
This repo is also a [[https://nixos.wiki/wiki/Flakes][Nix Flake]].
|
This repo is also a [[https://nixos.wiki/wiki/Flakes][Nix Flake]].
|
||||||
You can directly start a script with the following command if you have at least version 2.4 of [[https://nixos.org/][Nix]] installed:
|
You can directly start a script with the following command if you have at least version 2.4 of [[https://nixos.org/][Nix]] installed:
|
||||||
|
|
@ -20,7 +22,7 @@
|
||||||
: $ nix run github:Deleh/ffutils#<script_name> -- --help
|
: $ nix run github:Deleh/ffutils#<script_name> -- --help
|
||||||
|
|
||||||
** Scripts
|
** Scripts
|
||||||
|
|
||||||
*** =ffconv=
|
*** =ffconv=
|
||||||
:properties:
|
:properties:
|
||||||
:custom_id: ffconv
|
:custom_id: ffconv
|
||||||
|
|
@ -52,19 +54,19 @@
|
||||||
TO_FORMAT To format
|
TO_FORMAT To format
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-d, --directory DIRECTORY Convert files in DIRECTORY (default: current work d
|
-d, --directory DIRECTORY Convert files in DIRECTORY (default: current work
|
||||||
irectory)
|
directory)
|
||||||
-k, --keep Keep original files
|
-k, --keep Keep original files
|
||||||
-l, --list List files which match the FROM_FORMAT
|
-l, --list List files which match the FROM_FORMAT
|
||||||
-m, --move DIRECTORY Move old files to DIRECTORY (omits --keep) (default
|
-m, --move DIRECTORY Move old files to DIRECTORY (omits --keep)
|
||||||
: )
|
-h, --help Show this help message and exit
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
ffconv mp3 opus Convert all mp3 files to opus
|
ffconv mp3 opus Convert all mp3 files to opus
|
||||||
ffconv -m trash mp4 mkv Convert all mp4 to mkv and move the original one
|
ffconv -m trash mp4 mkv Convert all mp4 to mkv and move the original
|
||||||
s to './trash'
|
ones to './trash'
|
||||||
ffconv -d ~/music -l wma mp3 List all wma files from '~/music' and ask for co
|
ffconv -d ~/music -l wma mp3 List all wma files from '~/music' and ask for
|
||||||
nverting them to mp3
|
converting them to mp3
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
*** =ffcut=
|
*** =ffcut=
|
||||||
|
|
@ -79,7 +81,7 @@
|
||||||
Cutting file video.mp4
|
Cutting file video.mp4
|
||||||
The extracted part was saved to cutted_video.mp4
|
The extracted part was saved to cutted_video.mp4
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
**** Usage
|
**** Usage
|
||||||
|
|
||||||
#+begin_example
|
#+begin_example
|
||||||
|
|
@ -92,13 +94,14 @@
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-f, --from TIMESTAMP/SECONDS Extract from TIMESTAMP/SECONDS (default: 0)
|
-f, --from TIMESTAMP/SECONDS Extract from TIMESTAMP/SECONDS (default: 0)
|
||||||
-o, --out FILE Save extracted part to FILE (default: cutted_<fi
|
-o, --out FILE Save extracted part to FILE (default:
|
||||||
lename>)
|
cutted_<filename>)
|
||||||
-t, --to TIMESTAMP/DURATION Extract to TIMESTAMP/DURATION (default: end)
|
-t, --to TIMESTAMP/DURATION Extract to TIMESTAMP/DURATION (default: end)
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
ffcut -t 5 video.mp4 -o cut.webm Extract the first five seconds of 'vi
|
ffcut -t 5 video.mp4 -o cut.webm Extract the first five seconds of
|
||||||
deo.mp4' to 'cut.webm'
|
'video.mp4' to 'cut.webm'
|
||||||
ffcut -f 00:10:30 -t 00:14:15 video.mp4 Extract the part from 00:10:30 to 00:
|
ffcut -f 00:10:30 -t 00:14:15 video.mp4 Extract the part from 00:10:30 to
|
||||||
14:15 from 'video.mp4'
|
00:14:15 from 'video.mp4'
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ sfargs+=("move;m;DIRECTORY;;Move old files to DIRECTORY (omits --keep)")
|
||||||
sfexamples+=("ffconv mp3 opus;Convert all mp3 files to opus")
|
sfexamples+=("ffconv mp3 opus;Convert all mp3 files to opus")
|
||||||
sfexamples+=("ffconv -m trash mp4 mkv;Convert all mp4 to mkv and move the original ones to './trash'")
|
sfexamples+=("ffconv -m trash mp4 mkv;Convert all mp4 to mkv and move the original ones to './trash'")
|
||||||
sfexamples+=("ffconv -d ~/music -l wma mp3;List all wma files from '~/music' and ask for converting them to mp3")
|
sfexamples+=("ffconv -d ~/music -l wma mp3;List all wma files from '~/music' and ask for converting them to mp3")
|
||||||
|
sfdeps=("ffmpeg")
|
||||||
|
|
||||||
source "$(dirname $0)/../lib/sf"
|
source "$(dirname $0)/../lib/sf"
|
||||||
|
|
||||||
|
|
|
||||||
14
bin/ffcut
14
bin/ffcut
|
|
@ -8,23 +8,23 @@ sfargs+=("out;o;FILE;cutted_<filename>;Save extracted part to FILE")
|
||||||
sfargs+=("to;t;TIMESTAMP/DURATION;end;Extract to TIMESTAMP/DURATION")
|
sfargs+=("to;t;TIMESTAMP/DURATION;end;Extract to TIMESTAMP/DURATION")
|
||||||
sfexamples+=("ffcut -t 5 video.mp4 -o cut.webm;Extract the first five seconds of 'video.mp4' to 'cut.webm'")
|
sfexamples+=("ffcut -t 5 video.mp4 -o cut.webm;Extract the first five seconds of 'video.mp4' to 'cut.webm'")
|
||||||
sfexamples+=("ffcut -f 00:10:30 -t 00:14:15 video.mp4;Extract the part from 00:10:30 to 00:14:15 from 'video.mp4'")
|
sfexamples+=("ffcut -f 00:10:30 -t 00:14:15 video.mp4;Extract the part from 00:10:30 to 00:14:15 from 'video.mp4'")
|
||||||
|
sfdeps=("ffmpeg")
|
||||||
|
|
||||||
source "$(dirname $0)/../lib/sf"
|
source "$(dirname $0)/../lib/sf"
|
||||||
|
|
||||||
# Handle missing parameters
|
# Handle missing parameters
|
||||||
[ "$from" == 0 ] && [ "$to" == "end" ] && sferr "Set at least '--from' or '--to'"
|
[ "$from" == 0 ] && [ "$to" == "end" ] && sferr "Set at least ${sftbf}--from${sftrs} or ${sftbf}--to${sftrs}"
|
||||||
|
|
||||||
# Set default value for output file
|
# Set default value for output file
|
||||||
[ "$out" == "cutted_<filename>" ] && out="$(dirname "$FILE")/cutted_$(basename "$FILE")"
|
[ "$out" == "cutted_<filename>" ] && out="$(dirname "$FILE")/cutted_$(basename "$FILE")"
|
||||||
|
|
||||||
echo "Cutting file ${sftbf}$(basename "$FILE")${sftrs}"
|
|
||||||
|
|
||||||
# Set additional ffmpeg arguments
|
# Set additional ffmpeg arguments
|
||||||
ffmpeg_args=()
|
args=()
|
||||||
[ "$to" != "end" ] && ffmpeg_args+=("-t" "$to")
|
[ "$to" != "end" ] && args+=("-to" "$to")
|
||||||
[ "${FILE##*.}" == "${out##*.}" ] && ffmpeg_args+=("-c" "copy")
|
[ "${FILE##*.}" == "${out##*.}" ] && args+=("-c" "copy")
|
||||||
|
|
||||||
# Execute ffmpeg
|
# Execute ffmpeg
|
||||||
ffmpeg -hide_banner -loglevel error -ss "$from" -i "$FILE" -ss "$from" "${ffmpeg_args[@]}" "$out"
|
echo "Cutting file ${sftbf}$(basename "$FILE")${sftrs}"
|
||||||
|
ffmpeg -hide_banner -loglevel error -i "$FILE" -ss "$from" "${args[@]}" "$out"
|
||||||
|
|
||||||
[ "$?" == "0" ] && echo "The extracted part was saved to ${sftbf}$out${sftrs}"
|
[ "$?" == "0" ] && echo "The extracted part was saved to ${sftbf}$out${sftrs}"
|
||||||
|
|
|
||||||
180
lib/sf
180
lib/sf
|
|
@ -32,17 +32,21 @@ function sfwarn {
|
||||||
|
|
||||||
# Public input functions
|
# Public input functions
|
||||||
function sfask {
|
function sfask {
|
||||||
if [ "$2" == "" ]; then
|
if [ -n "$2" ]; then
|
||||||
read -p "$1? [${sftbf}Y${sftrs}/${sftbf}n${sftrs}] " sfin
|
read -r -p "$1? [${sftbf}y${sftrs}/${sftbf}N${sftrs}] " sfin
|
||||||
[[ "$sfin" =~ y|Y|^$ ]] && sfin=true || sfin=false
|
|
||||||
else
|
|
||||||
read -p "$1? [${sftbf}y${sftrs}/${sftbf}N${sftrs}] " sfin
|
|
||||||
[[ "$sfin" =~ n|N|^$ ]] && sfin=false || sfin=true
|
[[ "$sfin" =~ n|N|^$ ]] && sfin=false || sfin=true
|
||||||
|
else
|
||||||
|
read -r -p "$1? [${sftbf}Y${sftrs}/${sftbf}n${sftrs}] " sfin
|
||||||
|
[[ "$sfin" =~ y|Y|^$ ]] && sfin=true || sfin=false
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function sfget {
|
function sfget {
|
||||||
[ "$2" != "" ] && read -p "$1 [${sftbf}$2${sftrs}]: " sfin || read -p "$1: " sfin
|
if [ -n "$2" ]; then
|
||||||
|
read -r -p "$1 [${sftbf}$2${sftrs}]: " sfin
|
||||||
|
else
|
||||||
|
read -r -p "$1: " sfin
|
||||||
|
fi
|
||||||
[ "$sfin" == "" ] && [ "$2" != "" ] && sfin="$2"
|
[ "$sfin" == "" ] && [ "$2" != "" ] && sfin="$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,64 +59,82 @@ function _sferr {
|
||||||
# Declare variables for parsing
|
# Declare variables for parsing
|
||||||
OLDIFS=$IFS
|
OLDIFS=$IFS
|
||||||
IFS=";"
|
IFS=";"
|
||||||
_sfphead=""
|
|
||||||
_sfpdesc=""
|
|
||||||
_sfodesc=""
|
|
||||||
_sfexamples=""
|
|
||||||
_sfpargs=()
|
_sfpargs=()
|
||||||
|
_sfpheads=()
|
||||||
|
_sfpoffset=0
|
||||||
|
_sfptails=()
|
||||||
|
_sfpusage=""
|
||||||
|
_sfoheads=()
|
||||||
|
_sfooffset=0
|
||||||
|
_sfotails=()
|
||||||
declare -A _sfflags
|
declare -A _sfflags
|
||||||
declare -A _sfargs
|
declare -A _sfargs
|
||||||
|
|
||||||
# Parse sf arguments
|
# Parse sf arguments
|
||||||
|
sfargs=("${sfargs[@]}" "help;h;Show this help message and exit")
|
||||||
for a in "${sfargs[@]}"; do
|
for a in "${sfargs[@]}"; do
|
||||||
|
|
||||||
# Get amount of ;
|
# Get amount of ;
|
||||||
_sfsubst=${a//";"}
|
_sfsubst=${a//";"}
|
||||||
_sfcount="$(((${#a} - ${#_sfsubst})))"
|
_sfcount="$(((${#a} - ${#_sfsubst})))"
|
||||||
|
|
||||||
if [ $_sfcount -eq 1 ]; then
|
if [ "$_sfcount" -eq 1 ]; then
|
||||||
|
|
||||||
# Read positional argument declaration
|
# Read positional argument declaration
|
||||||
read -r -a _sfparsearr <<< "${a}"
|
read -r -a _sfparsearr <<< "${a}"
|
||||||
|
|
||||||
# Add to positional argument arry
|
# Add to positional argument arry
|
||||||
|
[[ " ${_sfpargs[*]} " =~ " ${_sfparsearr[0]} " ]] && _sferr "'${_sfparsearr[0]}' is already set: $a"
|
||||||
_sfpargs+=("${_sfparsearr[0]}")
|
_sfpargs+=("${_sfparsearr[0]}")
|
||||||
|
|
||||||
# Set usage header and description
|
# Set usage header and append description arrays
|
||||||
_sfphead="$_sfphead ${_sfparsearr[0]}"
|
_sfpusage="$_sfpusage ${_sfparsearr[0]}"
|
||||||
_sfpdesc="$_sfpdesc ${_sfparsearr[0]};${_sfparsearr[1]}\n"
|
_sfphead="${_sfparsearr[0]}"
|
||||||
|
[ "${#_sfphead}" -gt "${_sfpoffset}" ] && _sfpoffset="${#_sfphead}"
|
||||||
|
_sfpheads+=("$_sfphead")
|
||||||
|
_sfptails+=("${_sfparsearr[1]}")
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
elif [ $_sfcount -eq 2 ]; then
|
elif [ "$_sfcount" -eq 2 ]; then
|
||||||
|
|
||||||
# Read flag declaration
|
# Read flag declaration
|
||||||
read -r -a _sfparsearr <<< "${a}"
|
read -r -a _sfparsearr <<< "${a}"
|
||||||
|
|
||||||
# Set mappings
|
# Set mappings
|
||||||
_sfflags["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
|
[ -n "${_sfflags["--${_sfparsearr[0]}"]}" ] && _sferr "'${_sfparsearr[0]}' is already set: $a"
|
||||||
_sfflags["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
|
_sfflags["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
|
||||||
|
[ -n "${_sfflags["-${_sfparsearr[1]}"]}" ] && _sferr "'${_sfparsearr[1]}' is already set: $a"
|
||||||
|
_sfflags["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
|
||||||
|
|
||||||
# Set default value
|
# Set default value
|
||||||
declare ${_sfparsearr[0]}=false
|
declare "${_sfparsearr[0]//-/_}"=false
|
||||||
|
|
||||||
# Set description
|
# Append description arrays
|
||||||
_sfodesc="$_sfodesc -${_sfparsearr[1]}, --${_sfparsearr[0]};${_sfparsearr[2]}\n"
|
_sfohead="-${_sfparsearr[1]}, --${_sfparsearr[0]}"
|
||||||
|
[ "${#_sfohead}" -gt "${_sfooffset}" ] && _sfooffset="${#_sfohead}"
|
||||||
|
_sfoheads+=("$_sfohead")
|
||||||
|
_sfotails+=("${_sfparsearr[2]}")
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
elif [ $_sfcount -eq 4 ]; then
|
elif [ "$_sfcount" -eq 4 ]; then
|
||||||
|
|
||||||
# Read argument declaration
|
# Read argument declaration
|
||||||
read -r -a _sfparsearr <<< "${a}"
|
read -r -a _sfparsearr <<< "${a}"
|
||||||
|
|
||||||
# Set mappings
|
# Set mappings
|
||||||
_sfargs["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
|
[ -n "${_sfargs["--${_sfparsearr[0]}"]}" ] && _sferr "'${_sfparsearr[0]}' is already set: $a"
|
||||||
_sfargs["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
|
_sfargs["--${_sfparsearr[0]}"]="${_sfparsearr[0]}"
|
||||||
|
[ -n "${_sfargs["-${_sfparsearr[1]}"]}" ] && _sferr "'${_sfparsearr[1]}' is already set: $a"
|
||||||
|
_sfargs["-${_sfparsearr[1]}"]="${_sfparsearr[0]}"
|
||||||
|
|
||||||
# Set default value
|
# Set default value
|
||||||
declare ${_sfparsearr[0]}="${_sfparsearr[3]}"
|
declare "${_sfparsearr[0]//-/_}"="${_sfparsearr[3]}"
|
||||||
|
|
||||||
# Set description
|
# Append description arrays
|
||||||
_sfodesc="$_sfodesc -${_sfparsearr[1]}, --${_sfparsearr[0]} ${_sfparsearr[2]};${_sfparsearr[4]} (default: ${_sfparsearr[3]})\n"
|
_sfohead="-${_sfparsearr[1]}, --${_sfparsearr[0]} ${_sfparsearr[2]}"
|
||||||
|
[ "${#_sfohead}" -gt "${_sfooffset}" ] && _sfooffset="${#_sfohead}"
|
||||||
|
_sfoheads+=("$_sfohead")
|
||||||
|
[ "${_sfparsearr[3]}" != "" ] && _sfotails+=("${_sfparsearr[4]} (default: ${_sfparsearr[3]})") || _sfotails+=("${_sfparsearr[4]}")
|
||||||
|
|
||||||
else
|
else
|
||||||
_sferr "Wrong argument declaration: $a"
|
_sferr "Wrong argument declaration: $a"
|
||||||
|
|
@ -120,18 +142,26 @@ for a in "${sfargs[@]}"; do
|
||||||
done
|
done
|
||||||
|
|
||||||
# Parse examples
|
# Parse examples
|
||||||
|
_sfeheads=()
|
||||||
|
_sfetails=()
|
||||||
|
_sfeoffset=0
|
||||||
for e in "${sfexamples[@]}"; do
|
for e in "${sfexamples[@]}"; do
|
||||||
|
|
||||||
# Get amount of ;
|
# Get amount of ;
|
||||||
_sfsubst=${e//";"}
|
_sfsubst=${e//";"}
|
||||||
_sfcount="$(((${#e} - ${#_sfsubst})))"
|
_sfcount="$(((${#e} - ${#_sfsubst})))"
|
||||||
|
|
||||||
if [ $_sfcount -eq 1 ]; then
|
if [ "$_sfcount" -eq 1 ]; then
|
||||||
|
|
||||||
# Read example
|
# Read example
|
||||||
read -r -a _sfparsearr <<< "${e}"
|
read -r -a _sfparsearr <<< "${e}"
|
||||||
|
|
||||||
_sfexamples="$_sfexamples ${_sfparsearr[0]};${_sfparsearr[1]}\n"
|
# Append example arrays
|
||||||
|
_sfehead="${_sfparsearr[0]}"
|
||||||
|
[ "${#_sfehead}" -gt "${_sfeoffset}" ] && _sfeoffset="${#_sfehead}"
|
||||||
|
_sfeheads+=("$_sfehead")
|
||||||
|
_sfetails+=("${_sfparsearr[1]}")
|
||||||
|
|
||||||
else
|
else
|
||||||
_sferr "Wrong example declaration: $e"
|
_sferr "Wrong example declaration: $e"
|
||||||
fi
|
fi
|
||||||
|
|
@ -139,25 +169,76 @@ done
|
||||||
|
|
||||||
IFS=$OLDIFS
|
IFS=$OLDIFS
|
||||||
|
|
||||||
|
# Check if at least one positional argument is set if 'sfparr' is used
|
||||||
|
[ "$sfparr" == true ] && [ "${#_sfpargs[@]}" == 0 ] && _sferr "At least one positional argument must be used with 'sfparr'"
|
||||||
|
|
||||||
|
# Correct offsets
|
||||||
|
_sfpoffset=$(( "_sfpoffset" + 3 ))
|
||||||
|
_sfooffset=$(( "_sfooffset" + 3 ))
|
||||||
|
_sfeoffset=$(( "_sfeoffset" + 3 ))
|
||||||
|
|
||||||
|
# Set _sfwidth to current terminal width
|
||||||
|
_sfwidth=$(stty size | cut -d ' ' -f 2)
|
||||||
|
|
||||||
|
# Create positional argument description with correct line breaks
|
||||||
|
_sfpdesc=""
|
||||||
|
for i in "${!_sfptails[@]}"; do
|
||||||
|
_sfptail="${_sfptails[$i]}"
|
||||||
|
if [ "$(( ${#_sfptail} + _sfpoffset ))" -gt "$_sfwidth" ]; then
|
||||||
|
_sftmpwidth="$(( _sfwidth - _sfpoffset ))"
|
||||||
|
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
|
||||||
|
_sfptail=$(echo "$_sfptail" | fold -s -w "$_sftmpwidth")
|
||||||
|
_sfptail="${_sfptail//$' \n'/$'\n;'}"
|
||||||
|
fi
|
||||||
|
_sfpdesc="${_sfpdesc} ${_sfpheads[$i]};${_sfptail}\n"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create option description with correct line breaks
|
||||||
|
_sfodesc=""
|
||||||
|
for i in "${!_sfotails[@]}"; do
|
||||||
|
_sfotail="${_sfotails[$i]}"
|
||||||
|
if [ "$(( ${#_sfotail} + _sfooffset ))" -gt "$_sfwidth" ]; then
|
||||||
|
_sftmpwidth="$(( _sfwidth - _sfooffset ))"
|
||||||
|
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
|
||||||
|
_sfotail=$(echo "$_sfotail" | fold -s -w "$_sftmpwidth")
|
||||||
|
_sfotail="${_sfotail//$' \n'/$'\n;'}"
|
||||||
|
fi
|
||||||
|
_sfodesc="${_sfodesc} ${_sfoheads[$i]};${_sfotail}\n"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create examples description with correct line breaks
|
||||||
|
_sfexamples=""
|
||||||
|
for i in "${!_sfetails[@]}"; do
|
||||||
|
_sfetail="${_sfetails[$i]}"
|
||||||
|
if [ "$(( ${#_sfetail} + _sfeoffset ))" -gt "$_sfwidth" ]; then
|
||||||
|
_sftmpwidth="$(( _sfwidth - _sfeoffset ))"
|
||||||
|
_sftmpwidth=$(echo -e "${_sftmpwidth}\n1" | sort -nr | head -n 1)
|
||||||
|
_sfetail=$(echo "$_sfetail" | fold -s -w "$_sftmpwidth")
|
||||||
|
_sfetail="${_sfetail//$' \n'/$'\n;'}"
|
||||||
|
fi
|
||||||
|
_sfexamples="${_sfexamples} ${_sfeheads[$i]};${_sfetail}\n"
|
||||||
|
done
|
||||||
|
|
||||||
# Usage function
|
# Usage function
|
||||||
function _sfusage {
|
function _sfusage {
|
||||||
echo -n "Usage: $(basename $0)"
|
echo -n "Usage: $(basename "$0") [OPTIONS]"
|
||||||
[ "$_sfodesc" != "" ] && echo -n " [OPTIONS]"
|
echo -ne "$_sfpusage"
|
||||||
echo -e "$_sfphead"
|
[ "$sfparr" == true ] && echo -n " ..."
|
||||||
[ ! -z ${sfdesc+x} ] && echo -e "\n$sfdesc"
|
echo
|
||||||
|
[ -n "${sfdesc}" ] && echo -e "\n$sfdesc" | fold -s -w "$_sfwidth"
|
||||||
if [ "$_sfpdesc" != "" ]; then
|
if [ "$_sfpdesc" != "" ]; then
|
||||||
echo -e "\nPOSITIONAL ARGUMENTS"
|
echo -e "\nPOSITIONAL ARGUMENTS"
|
||||||
echo -e "$_sfpdesc" | column -c 80 -s ";" -t -W 2
|
echo -e "$_sfpdesc" | column -s ";" -t -W 2
|
||||||
fi
|
fi
|
||||||
if [ "$_sfodesc" != "" ]; then
|
if [ "$_sfodesc" != "" ]; then
|
||||||
echo -e "\nOPTIONS"
|
echo -e "\nOPTIONS"
|
||||||
echo -e "$_sfodesc" | column -c 80 -s ";" -t -W 2
|
echo -e "$_sfodesc" | column -s ";" -t -W 2
|
||||||
fi
|
fi
|
||||||
if [ "$_sfexamples" != "" ]; then
|
if [ "$_sfexamples" != "" ]; then
|
||||||
echo -e "\nEXAMPLES"
|
echo -e "\nEXAMPLES"
|
||||||
echo -e "$_sfexamples" | column -c 80 -s ";" -t -W 2
|
echo -e "$_sfexamples" | column -s ";" -t -W 2
|
||||||
fi
|
fi
|
||||||
if [ ! -z ${sfextra+x} ]; then
|
if [ -n "${sfextra}" ]; then
|
||||||
echo -e "\n$sfextra"
|
echo -e "\n$sfextra"
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|
@ -169,19 +250,28 @@ for a in "$@"; do
|
||||||
[ "$a" == "-h" ] || [ "$a" == "--help" ] && _sfusage
|
[ "$a" == "-h" ] || [ "$a" == "--help" ] && _sfusage
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Check if dependencies are available
|
||||||
|
for d in "${sfdeps[@]}"; do
|
||||||
|
if ! command -v "$d" &> /dev/null; then
|
||||||
|
sferr "Command ${sftbf}${d}${sftrs} not found" 0
|
||||||
|
_sfdeperr=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ "$_sfdeperr" == true ] && exit 1
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
while (( "$#" )); do
|
while (( "$#" )); do
|
||||||
|
|
||||||
# Check if flag
|
# Check if flag
|
||||||
if [ ! -z ${_sfflags["$1"]} ]; then
|
if [ -n "${_sfflags["$1"]}" ]; then
|
||||||
declare ${_sfflags["$1"]}=true
|
declare "${_sfflags["$1"]//-/_}"=true
|
||||||
|
|
||||||
# Check if argument
|
# Check if argument
|
||||||
elif [ ! -z ${_sfargs["$1"]} ]; then
|
elif [ -n "${_sfargs["$1"]}" ]; then
|
||||||
|
|
||||||
# Check if argument has value
|
# Check if argument has value
|
||||||
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
|
||||||
declare ${_sfargs["$1"]}="$2"
|
declare "${_sfargs["$1"]//-/_}"="$2"
|
||||||
shift
|
shift
|
||||||
else
|
else
|
||||||
sferr "Argument for '$1' missing"
|
sferr "Argument for '$1' missing"
|
||||||
|
|
@ -191,12 +281,15 @@ while (( "$#" )); do
|
||||||
else
|
else
|
||||||
# Check if arg starts with -
|
# Check if arg starts with -
|
||||||
if [ "${1:0:1}" == "-" ]; then
|
if [ "${1:0:1}" == "-" ]; then
|
||||||
sferr "Unsupported argument: $1"
|
sferr "Unsupported argument/flag: $1"
|
||||||
else
|
else
|
||||||
# Set positional argument
|
# Set positional argument
|
||||||
if [ "${#_sfpargs[@]}" != 0 ]; then
|
if [ "${#_sfpargs[@]}" != 0 ]; then
|
||||||
declare ${_sfpargs[0]}="$1"
|
declare "${_sfpargs[0]//-/_}"="$1"
|
||||||
|
[ "$sfparr" == true ] && _sfplast="${_sfpargs[0]//-/_}" && _sfparr=("$1")
|
||||||
_sfpargs=("${_sfpargs[@]:1}")
|
_sfpargs=("${_sfpargs[@]:1}")
|
||||||
|
elif [ "$sfparr" == true ]; then
|
||||||
|
_sfparr+=("$1")
|
||||||
else
|
else
|
||||||
sferr "Too many positional arguments"
|
sferr "Too many positional arguments"
|
||||||
fi
|
fi
|
||||||
|
|
@ -205,8 +298,11 @@ while (( "$#" )); do
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Parse additional arguments if 'sfparr' is set
|
||||||
|
[ "$sfparr" == true ] && [ "${#_sfparr[@]}" -gt 0 ] && read -r -a "${_sfplast?}" <<< "${_sfparr[@]}"
|
||||||
|
|
||||||
# Check if positional arguments left
|
# Check if positional arguments left
|
||||||
if [ ${#_sfpargs[@]} != 0 ]; then
|
if [ "${#_sfpargs[@]}" -gt 0 ]; then
|
||||||
for p in "${_sfpargs[@]}"; do
|
for p in "${_sfpargs[@]}"; do
|
||||||
sferr "Positional argument '$p' missing" 0
|
sferr "Positional argument '$p' missing" 0
|
||||||
done
|
done
|
||||||
|
|
@ -214,4 +310,4 @@ if [ ${#_sfpargs[@]} != 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Unset all internal variables and functions
|
# Unset all internal variables and functions
|
||||||
unset a e _sfphead _sfpdesc _sfodesc _sfexamples _sfpargs _sfflags _sfargs _sferr _sfusage
|
unset a d e i OLDIFS _sfargs _sfehead _sfeheads _sfeoffset _sferr _sfetails _sfexamples _sfflags _sfodesc _sfohead _sfoheads _sfooffset _sfotails _sfpargs _sfparr _sfpdesc _sfphead _sfpheads _sfplast _sfpoffset _sfptails _sfpusage _sftmpwidth _sfusage _sfwidth
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue