aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Fink2026-05-10 20:37:01 +0200
committerDennis Fink2026-05-10 20:37:01 +0200
commiteecaf6c4b9b5c6c248302e7db2bb15b7ca1c6b29 (patch)
tree3e2d461decedce7e61a9dd5beffb0ba93ce99ba1
parent46e56972f2b4d16ca6b3fd04611f86cf8580ea10 (diff)
downloadtranscode.sh-eecaf6c4b9b5c6c248302e7db2bb15b7ca1c6b29.tar.gz
transcode.sh-eecaf6c4b9b5c6c248302e7db2bb15b7ca1c6b29.zip
feat(preset): add --list-presets to enumerate available presets
Print all *.sh files found in $PRESET_DIR, one per line, with a one-line description extracted from the first line of each file if it matches a `# description: …` comment. Presets without such a comment are listed without a description. Symlinks pointing to another preset inside $PRESET_DIR are shown as "<name> - Symlinked to <target>" rather than duplicating the description. Symlinks pointing outside $PRESET_DIR are followed and treated as regular preset files. Column width for preset names is calculated from the longest name in the directory so descriptions align with minimal padding. Also extracts the repeated readlink/realpath idiom into a dedicated resolve_path() helper and adds a doc comment to filesize(). Exits immediately after printing (same pattern as --version/--help). Honours --quiet/NO_COLOR via the existing msg() and color infrastructure.
Diffstat (limited to '')
-rw-r--r--README.md16
-rwxr-xr-xtranscode.sh80
-rw-r--r--transcode.sh.19
-rw-r--r--transcode.sh.bash-completion1
4 files changed, 105 insertions, 1 deletions
diff --git a/README.md b/README.md
index a3adaf4..8ce5e12 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,21 @@ ffargs=(
> **Security:** presets are executed as shell code. Only use presets from
> trusted sources.
+A preset may carry an optional one-line description as a shell comment:
+
+```sh
+# description: Encode to AV1 with SVT-AV1 at a balanced quality/speed trade-off
+ffargs=(
+ -c:v:0 libsvtav1
+ -crf 30
+ -preset 6
+ -pix_fmt "$output_pixel_format"
+)
+```
+
+Run `transcode.sh --list-presets` to enumerate all presets in the preset
+directory and display their descriptions.
+
### Configuration file
An optional TOML configuration file can be placed at:
@@ -194,6 +209,7 @@ transcode.sh [OPTION] [--] FILE...
| `-v`, `--verbose` | More detailed output |
| `--color` / `--no-color` | Force or disable colored output |
| `--version` | Print version information |
+| `--list-presets` | List available presets (name + description) and exit |
| `-h`, `-?`, `--help` | Show help and exit |
### Examples
diff --git a/transcode.sh b/transcode.sh
index 41a22ab..f89732c 100755
--- a/transcode.sh
+++ b/transcode.sh
@@ -266,6 +266,7 @@ ${BOLD}${BLUE}Output options:${ALL_OFF}
${BOLD}${BLUE}General options:${ALL_OFF}
${BOLD}${YELLOW}-h, --help${ALL_OFF} display this help and exit
${BOLD}${YELLOW}--version${ALL_OFF} output version information and exit
+ ${BOLD}${YELLOW}--list-presets${ALL_OFF} list available presets and exit
${BOLD}${BLUE}Configuration files:${ALL_OFF}
${BOLD}${CYAN}%s/<NAME>.sh${ALL_OFF}
@@ -335,10 +336,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" \
"$DATE_OF_REVISION" "$LICENSE"
}
+# Return the size of a file in bytes.
+# Uses GNU stat -c on Linux with a fallback to BSD/macOS stat -f.
filesize() {
stat -c "%s" -- "$1" 2>/dev/null || stat -f "%z" -- "$1"
}
+# Resolve a symlink (or plain path) to its canonical absolute path.
+# Uses readlink -f (GNU) with a fallback to realpath for macOS/BSD.
+resolve_path() {
+ readlink -f -- "$1" 2>/dev/null || realpath -- "$1"
+}
+
###############################################################################
# TERMINAL COLOR SETUP
#
@@ -620,7 +629,7 @@ load_preset() {
# of the symlink itself (always 777 on Linux), not the target. We use
# readlink -f (GNU) with a fallback to realpath for macOS/BSD.
local resolved_file
- resolved_file=$(readlink -f -- "$file" 2>/dev/null || realpath -- "$file")
+ resolved_file=$(resolve_path "$file")
local preset_perms
preset_perms=$(stat -c '%a' -- "$resolved_file" 2>/dev/null || stat -f '%OLp' -- "$resolved_file")
@@ -646,6 +655,71 @@ load_preset() {
debug "Preset ffargs:" "$(printf "%q " "${ffargs[@]}")"
}
+# List all presets in PRESET_DIR, printing their name and optional description.
+#
+# A description is read from the first line of the preset file only.
+# If that line matches: # description: <text>
+# (case-insensitive, leading whitespace ignored) the text is extracted;
+# otherwise the preset is listed without a description.
+#
+# Symlink handling:
+# - A symlink whose target resolves to another *.sh file inside PRESET_DIR
+# is shown as "<name> -> <target-name>" with no description (the target
+# entry already carries it).
+# - A symlink pointing outside PRESET_DIR is followed and treated as a
+# regular preset file (description is read from its content).
+list_presets() {
+ if [[ ! -d "$PRESET_DIR" ]]; then
+ warn "Preset directory does not exist:" "$PRESET_DIR"
+ return $EXIT_OK
+ fi
+
+ local -a preset_files=()
+ local f name max_name_len=0
+ for f in "$PRESET_DIR"/*.sh; do
+ if [[ -f "$f" ]]; then
+ preset_files+=("$f")
+ name="${f##*/}"
+ name="${name%.sh}"
+ ((${#name} > max_name_len)) && max_name_len=${#name}
+ fi
+ done
+
+ if [[ ${#preset_files[@]} -eq 0 ]]; then
+ msg "No presets found in:" "$PRESET_DIR"
+ return $EXIT_OK
+ fi
+
+ local canonical_preset_dir
+ canonical_preset_dir=$(resolve_path "$PRESET_DIR")
+
+ printf "${BOLD}${BLUE}Available presets in${ALL_OFF} ${BOLD}${CYAN}%s${ALL_OFF}${BOLD}${BLUE}:${ALL_OFF}\n" "$PRESET_DIR"
+
+ local target_path target_name description
+ for f in "${preset_files[@]}"; do
+ name="${f##*/}"
+ name="${name%.sh}"
+
+ if [[ -L "$f" ]]; then
+ target_path=$(resolve_path "$f")
+
+ if [[ "$target_path" == "$canonical_preset_dir"/*.sh ]]; then
+ target_name="${target_path##*/}"
+ target_name="${target_name%.sh}"
+ printf " ${BOLD}${GREEN}%-${max_name_len}s${ALL_OFF} ${BOLD}${YELLOW}-${ALL_OFF} Symlinked to ${BOLD}${GREEN}%s${ALL_OFF}\n" "$name" "$target_name"
+ continue
+ fi
+ fi
+
+ description=$(sed -n '1s/^[[:space:]]*#[[:space:]]*[Dd]escription:[[:space:]]*//p' "$f")
+ if [[ -n "$description" ]]; then
+ printf " ${BOLD}${GREEN}%-${max_name_len}s${ALL_OFF} ${BOLD}${YELLOW}-${ALL_OFF} %s\n" "$name" "$description"
+ else
+ printf " ${BOLD}${GREEN}%-${max_name_len}s${ALL_OFF}\n" "$name"
+ fi
+ done
+}
+
if [[ $# -eq 0 ]]; then
debug "No parameters were specified"
printf "${BOLD}${BLUE}Usage:${ALL_OFF} ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}[OPTION] [--]${ALL_OFF} ${BOLD}${GREEN}FILE...${ALL_OFF}
@@ -663,6 +737,10 @@ while [[ $# -gt 0 ]]; do
print_version
exit $EXIT_OK
;;
+ --list-presets)
+ list_presets
+ exit $EXIT_OK
+ ;;
-q | --quiet)
QUIET=1
_CLI_QUIET=1
diff --git a/transcode.sh.1 b/transcode.sh.1
index 46b7526..af03bf9 100644
--- a/transcode.sh.1
+++ b/transcode.sh.1
@@ -174,6 +174,15 @@ etc.).
.B \-\-version
Print version, author and license information and exit.
.TP
+.B \-\-list\-presets
+Print all preset names found in the preset directory, along with their
+one-line description (read from a
+.B # description:
+comment on the first line of the preset file), then exit.
+If the preset directory does not exist or contains no
+.B .sh
+files, a notice is printed instead.
+.TP
.B \-\-color
Force colored output even when stdout is not a terminal or
.B NO_COLOR
diff --git a/transcode.sh.bash-completion b/transcode.sh.bash-completion
index 1cae90e..2749882 100644
--- a/transcode.sh.bash-completion
+++ b/transcode.sh.bash-completion
@@ -138,6 +138,7 @@ _transcode_sh() {
--help
--hwaccel
--hwaccel=
+ --list-presets
--nice
--nice=
--no-color