diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-06-04 13:44:13 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-06-04 13:44:13 +0900 |
| commit | 945a128577bda089d7b3d7510c9d4b4b69d0fe6e (patch) | |
| tree | be09b3b78dad58645fe63e548ffe12a1846a9846 /ar | |
| parent | e2d67a8f88acb79e6477f352f42ec1684154b2f8 (diff) | |
modified lf/lfrc, modified bin/ccv
Diffstat (limited to 'ar')
| -rw-r--r-- | ar/.config/lf/lfrc | 218 | ||||
| -rwxr-xr-x | ar/.local/bin/ccv | 96 |
2 files changed, 231 insertions, 83 deletions
diff --git a/ar/.config/lf/lfrc b/ar/.config/lf/lfrc index a69d578..321f2b7 100644 --- a/ar/.config/lf/lfrc +++ b/ar/.config/lf/lfrc @@ -86,13 +86,18 @@ cmd compress ${{ cmd copyto ${{ set -f clear; tput cup $(($(tput lines)/3)) - dest=$( - { - sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" - findmnt -rno TARGET | grep -E "^/mnt/|^/media/$USER/" - } | awk '!seen[$0]++' | fzf --layout=reverse --height 40% --prompt 'Copy to where? ' | sed 's|~|$HOME|') + tmpdest=$(mktemp) + { + sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" + findmnt -rno TARGET | grep -E "^/mnt/|^/media/$USER/" | while read -r m; do + printf '%s\n' "$m" + find "$m" -mindepth 1 -maxdepth 2 -type d -not -name '.*' 2>/dev/null || true + done + } | awk '!seen[$0]++' | fzf --layout=reverse --height 40% --prompt 'Copy to where? ' > "$tmpdest" || true + IFS= read -r dest < "$tmpdest" || dest="" + rm -f "$tmpdest" [ -z "$dest" ] && exit - destpath=$(eval printf '%s' \"$dest\") + case "$dest" in "~"*) destpath="$HOME${dest#?}";; *) destpath="$dest";; esac clear; tput cup $(($(tput lines)/3)); tput bold echo "From:" echo "$fx" | sed 's/^/ /' @@ -121,7 +126,10 @@ cmd mkdir %{{ IFS=" " file="$*" mkdir -p -- "$file" - lf -remote "send $id cd \"$(printf '%s' "$file" | sed 's/\\/\\\\/g;s/"/\\"/g')\"" + printf '%s' "$file" | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r quoted || quoted="$file" + lf -remote "send $id cd \"$quoted\"" + } }} cmd touch %{{ IFS=" " @@ -133,11 +141,16 @@ cmd touch %{{ dir="${file%/*}" [ "$dir" != "$file" ] && mkdir -p -- "$dir" touch -- "$file" - file="$(printf '%s' "$file" | sed 's/\\/\\\\/g;s/"/\\"/g')" - lf -remote "send $id :select \"$file\"; \$\$EDITOR \"$file\"" + printf '%s' "$file" | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r quoted || quoted="$file" + lf -remote "send $id :select \"$quoted\"; \$\$EDITOR \"$quoted\"" + } }} cmd link %{{ - set -- $(cat ~/.local/share/lf/files) + set -- + while IFS= read -r line || [ -n "$line" ]; do + set -- "$@" "$line" + done < ~/.local/share/lf/files mode="$1" shift if [ "$#" -lt 1 ]; then @@ -216,8 +229,7 @@ cmd dragon-individual &{{ lf -remote "send $id :unselect; save-select" }} cmd dragon-target ${{ - out=$(dragon-drop -t -x) - [ -n "$out" ] && printf "%s\n" "$out" | while IFS= read -r src; do + dragon-drop -t -x | while IFS= read -r src; do [ -e "$src" ] && cp -ivr "$src" "$PWD" done lf -remote "send $id :unselect; save-select" @@ -269,17 +281,13 @@ cmd extract ${{ *) printf "Unknown archive type: %s\n" "$archive"; continue;; esac + # count only (ASCII) — entry names must not pass through dash's $() case "$type" in - tar) toplevel=$(tar tf "$archive" 2>/dev/null | awk -F/ 'NF{print $1}' | sort -u);; - 7z) toplevel=$(7z l -slt -ba "$archive" 2>/dev/null | awk -F'= ' '/^Path = /{print $2}' | awk -F/ 'NF{print $1}' | sort -u);; - rar) toplevel=$(unrar lb "$archive" 2>/dev/null | awk -F/ 'NF{print $1}' | sort -u);; - *) toplevel="";; + tar) count=$(tar tf "$archive" 2>/dev/null | awk -F/ 'NF{print $1}' | sort -u | grep -c . || true);; + 7z) count=$(7z l -slt -ba "$archive" 2>/dev/null | awk -F'= ' '/^Path = /{print $2}' | awk -F/ 'NF{print $1}' | sort -u | grep -c . || true);; + rar) count=$(unrar lb "$archive" 2>/dev/null | awk -F/ 'NF{print $1}' | sort -u | grep -c . || true);; + *) count=0;; esac - if [ -z "$toplevel" ]; then - count=0 - else - count=$(printf '%s\n' "$toplevel" | wc -l) - fi target="." if [ "$count" != "1" ]; then @@ -303,12 +311,14 @@ cmd extract ${{ # Git cmd git-root %{{ - root=$(git rev-parse --show-toplevel 2>/dev/null) - if [ -n "$root" ]; then - lf -remote "send $id cd \"$root\"" - else - lf -remote "send $id echo 'Not in a git repository'" - fi + { git rev-parse --show-toplevel 2>/dev/null || true; } | { + IFS= read -r root || root="" + if [ -n "$root" ]; then + lf -remote "send $id cd \"$root\"" + else + lf -remote "send $id echo 'Not in a git repository'" + fi + } }} cmd on-cd &{{ @@ -328,7 +338,8 @@ cmd on-cd &{{ }} cmd on-load &{{ - cd "$(dirname "$1")" || exit 1 + dir="${1%/*}" + cd "${dir:-/}" || exit 1 [ "$(git rev-parse --is-inside-git-dir 2>/dev/null)" = false ] || exit 0 cmds="" for file in "$@"; do @@ -359,13 +370,18 @@ cmd create-ipynb ${{ cmd moveto ${{ set -f clear; tput cup $(($(tput lines)/3)) - dest=$( - { - sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" - findmnt -rno TARGET | grep -E "^/mnt/|^/media/$USER/" - } | awk '!seen[$0]++' | fzf --layout=reverse --height 40% --prompt 'Move to where? ' | sed 's|~|$HOME|') + tmpdest=$(mktemp) + { + sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" + findmnt -rno TARGET | grep -E "^/mnt/|^/media/$USER/" | while read -r m; do + printf '%s\n' "$m" + find "$m" -mindepth 1 -maxdepth 2 -type d -not -name '.*' 2>/dev/null || true + done + } | awk '!seen[$0]++' | fzf --layout=reverse --height 40% --prompt 'Move to where? ' > "$tmpdest" || true + IFS= read -r dest < "$tmpdest" || dest="" + rm -f "$tmpdest" [ -z "$dest" ] && exit - destpath=$(eval printf '%s' \"$dest\") + case "$dest" in "~"*) destpath="$HOME${dest#?}";; *) destpath="$dest";; esac clear; tput cup $(($(tput lines)/3)); tput bold echo "From:" echo "$fx" | sed 's/^/ /' @@ -391,10 +407,14 @@ cmd mpvdir ${{ set -- $fx setsid -f mpv --x11-name=video --really-quiet -- "$@" </dev/null >/dev/null 2>&1 else - for file in $(printf '%s\n' *.mp4 *.mkv *.avi *.flv *.webm *.mov *.mpg *.3gp *.ts *.rmvb | sort -f); do + tmplist=$(mktemp) + printf '%s\n' *.mp4 *.mkv *.avi *.flv *.webm *.mov *.mpg *.3gp *.ts *.rmvb | sort -f > "$tmplist" + set -- + while IFS= read -r file; do [ -e "$file" ] && set -- "$@" "$file" - done - [ -n "$1" ] && setsid -f mpv --x11-name=video --really-quiet -- "$@" </dev/null >/dev/null 2>&1 + done < "$tmplist" + rm -f "$tmplist" + [ "$#" -gt 0 ] && setsid -f mpv --x11-name=video --really-quiet -- "$@" </dev/null >/dev/null 2>&1 fi lf -remote "send $id :clear; unselect; save-select" @@ -402,7 +422,7 @@ cmd mpvdir ${{ # Open cmd open ${{ - case $(file --mime-type "$(readlink -f $f)" -b) in + case $(file -bL --mime-type -- "$f") in application/octet-stream) case ${f##*.} in ppt|pptx) setsid -f libreoffice --impress $fx >/dev/null 2>&1 ;; @@ -443,21 +463,41 @@ cmd open ${{ cmd bulkrename ${{ tmpfile_old="$(mktemp)" tmpfile_new="$(mktemp)" - - [ -n "$fs" ] && fs=$(basename -a $fs) || fs=$([ "$lf_hidden" = "true" ] && ls -A || ls) - - echo "$fs" > "$tmpfile_old" - echo "$fs" > "$tmpfile_new" + tmpfile_failed="$(mktemp)" + + # NOTE: avoid command substitution over multibyte data — dash's $() corrupts + # UTF-8 chars straddling its 128-byte read buffer (stray 0x81 CTLESC bytes) + if [ -n "$fs" ]; then + printf '%s\n' "$fs" | xargs -d '\n' -r basename -a -- > "$tmpfile_old" + elif [ "$lf_hidden" = "true" ]; then + ls -A > "$tmpfile_old" + else + ls > "$tmpfile_old" + fi + cp "$tmpfile_old" "$tmpfile_new" $EDITOR "$tmpfile_new" - [ "$(wc -l < "$tmpfile_old")" -eq "$(wc -l < "$tmpfile_new")" ] || { rm -f "$tmpfile_old" "$tmpfile_new"; exit 1; } + [ "$(wc -l < "$tmpfile_old")" -eq "$(wc -l < "$tmpfile_new")" ] || { rm -f "$tmpfile_old" "$tmpfile_new" "$tmpfile_failed"; exit 1; } paste "$tmpfile_old" "$tmpfile_new" | while IFS="$(printf '\t')" read -r src dst do - [ "$src" = "$dst" ] || [ -e "$dst" ] || mv -- "$src" "$dst" + [ "$src" = "$dst" ] || [ -e "$dst" ] || + mv -- "$src" "$dst" 2>/dev/null || + printf '%s\t%s\n' "$src" "$dst" >> "$tmpfile_failed" done - rm -f "$tmpfile_old" "$tmpfile_new" + if [ -s "$tmpfile_failed" ]; then + clear; tput cup $(($(tput lines)/3)); tput bold + cut -f1 "$tmpfile_failed" + printf "Permission needed for %s file(s). Rename with sudo?[y/N]" "$(wc -l < "$tmpfile_failed")" + read -r ans + [ "$ans" = "y" ] && while IFS="$(printf '\t')" read -r src dst + do + sudo mv -- "$src" "$dst" + done < "$tmpfile_failed" + fi + + rm -f "$tmpfile_old" "$tmpfile_new" "$tmpfile_failed" lf -remote "send $id unselect" }} @@ -493,9 +533,9 @@ cmd select-mime &{{ [ -s /tmp/lf-select-mime-$$ ] || { rm -f /tmp/lf-select-mime-$$; exit; } lf -remote "send $id unselect" + sed 's/\\/\\\\/g;s/"/\\"/g' /tmp/lf-select-mime-$$ > /tmp/lf-select-mime-q-$$ batch="" - while IFS= read -r file; do - quoted=$(printf '%s' "$file" | sed 's/\\/\\\\/g;s/"/\\"/g') + while IFS= read -r quoted; do candidate="$batch \"$quoted\"" if [ ${#candidate} -gt 8000 ]; then lf -remote "send $id toggle $batch" @@ -503,9 +543,9 @@ cmd select-mime &{{ else batch="$candidate" fi - done < /tmp/lf-select-mime-$$ + done < /tmp/lf-select-mime-q-$$ [ -n "$batch" ] && lf -remote "send $id toggle $batch" - rm -f /tmp/lf-select-mime-$$ + rm -f /tmp/lf-select-mime-$$ /tmp/lf-select-mime-q-$$ }} cmd select-dirs select-mime 'inode/directory' cmd select-files select-mime '-inode/directory' @@ -513,7 +553,10 @@ cmd select-videos select-mime 'video/' cmd select-images select-mime 'image/' cmd select-music select-mime 'audio/' cmd on-select &{{ - lf -remote "send $id set statfmt \"$(eza -ldg --color=always "$f")\"" + eza -ldg --color=always "$f" | { + IFS= read -r line || line="" + lf -remote "send $id set statfmt \"$line\"" + } }} cmd load-select &{{ if [ $# -eq 1 ] && [ "$1" = "$id" ]; then @@ -521,7 +564,13 @@ cmd load-select &{{ fi lf -remote "send $id unselect" if [ -s ~/.local/share/lf/select ]; then - files="$(sed 's/\\/\\\\/g;s/"/\\"/g;s/^/"/;s/$/"/' ~/.local/share/lf/select | tr '\n' ' ')" + tmpq=$(mktemp) + sed 's/\\/\\\\/g;s/"/\\"/g;s/^/"/;s/$/"/' ~/.local/share/lf/select > "$tmpq" + files="" + while IFS= read -r line || [ -n "$line" ]; do + files="$files $line" + done < "$tmpq" + rm -f "$tmpq" lf -remote "send $id toggle $files" fi }} @@ -545,34 +594,51 @@ cmd alt-paste &{{ }} # Traversal -cmd fzf $nvim $(find . -name "$1" | fzf) +cmd fzf ${{ + tmpsel=$(mktemp) + find . -name "$1" | fzf > "$tmpsel" || true + IFS= read -r sel < "$tmpsel" || sel="" + rm -f "$tmpsel" + if [ -n "$sel" ]; then nvim -- "$sel"; fi +}} cmd fzf_search ${{ RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case " - res="$( - FZF_DEFAULT_COMMAND="$RG_PREFIX ''" \ - fzf --bind "change:reload:$RG_PREFIX {q} || true" \ - --ansi --layout=reverse --header 'Search in files' \ - | cut -d':' -f1 | sed 's/\\/\\\\/g;s/"/\\"/g' - )" - [ -n "$res" ] && lf -remote "send $id select \"$res\"" + FZF_DEFAULT_COMMAND="$RG_PREFIX ''" \ + fzf --bind "change:reload:$RG_PREFIX {q} || true" \ + --ansi --layout=reverse --header 'Search in files' \ + | cut -d':' -f1 | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r res || res="" + if [ -n "$res" ]; then lf -remote "send $id select \"$res\""; fi + } }} cmd z %{{ - result="$(zoxide query --exclude $PWD $@ | sed 's/\\/\\\\/g;s/"/\\"/g')" - lf -remote "send $id cd \"$result\"" + { zoxide query --exclude $PWD $@ 2>/dev/null || true; } | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r result || result="" + if [ -n "$result" ]; then lf -remote "send $id cd \"$result\""; fi + } }} cmd zi ${{ - result="$(zoxide query -i | sed 's/\\/\\\\/g;s/"/\\"/g')" - lf -remote "send $id cd \"$result\"" + { zoxide query -i 2>/dev/null || true; } | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r result || result="" + if [ -n "$result" ]; then lf -remote "send $id cd \"$result\""; fi + } }} cmd follow_link %{{ - lf -remote "send ${id} select '$(readlink $f)'" + { readlink -- "$f" || true; } | sed 's/\\/\\\\/g;s/"/\\"/g' | { + IFS= read -r target || target="" + if [ -n "$target" ]; then lf -remote "send ${id} select \"$target\""; fi + } }} cmd lastfiles ${{ - list=$(nvim -u NONE --headless +'lua io.write(table.concat(vim.v.oldfiles, "\n") .. "\n")' +qa) - file=$(printf "%s" "$list" | while read -r file; do + tmplist=$(mktemp) + tmpsel=$(mktemp) + nvim -u NONE --headless +'lua io.write(table.concat(vim.v.oldfiles, "\n") .. "\n")' +qa > "$tmplist" + while IFS= read -r file; do [ -f "$file" ] && printf "%s\n" "$file" - done | fzf --reverse || lf -remote "send $id reload") - [ -n "$file" ] && $EDITOR "$file" + done < "$tmplist" | fzf --reverse > "$tmpsel" || lf -remote "send $id reload" + IFS= read -r file < "$tmpsel" || file="" + rm -f "$tmplist" "$tmpsel" + if [ -n "$file" ]; then $EDITOR "$file"; fi }} cmd edit-config ${{ $EDITOR ~/.config/lf/lfrc @@ -580,7 +646,7 @@ cmd edit-config ${{ }} cmd wine-run ${{ - if [ $(file --mime-type "$(readlink -f $f)" -b) = "application/vnd.microsoft.portable-executable" ]; then + if [ "$(file -bL --mime-type -- "$f")" = "application/vnd.microsoft.portable-executable" ]; then file="${f##*/}" file="${file%.*}" export WINEPREFIX="${WINEPREFIX:-${XDG_DATA_HOME:-${HOME}/.local/share}/wine}/$file" @@ -658,7 +724,7 @@ map <enter> $$EDITOR "$f" map <c-v> push :!nvim<space> map vlf edit-config map vll lastfiles -map vln $$EDITOR "$(nvim -u NONE --headless +'lua io.write(vim.v.oldfiles[1] .. "\n")' +qa)" +map vln $nvim -u NONE --headless +'lua io.write(vim.v.oldfiles[1] .. "\n")' +qa | { IFS= read -r file || exit 0; if [ -f "$file" ]; then $EDITOR "$file" < /dev/tty; fi; } # Extract map E extract; clear; save-select @@ -682,7 +748,7 @@ map Mv moveto; clear; save-select map Mpv mpvdir # Nsxiv -map th $nsxiv -apt "$(pwd)" +map th $nsxiv -apt "$PWD" # Open map O $mimeopen "$f" @@ -748,11 +814,11 @@ map st :set sortby time; set info time map tg tag-toggle # Traversal -map fa $lf -remote "send $id select \"$(fzf)\"" -map fb $lf -remote "send $id cd $(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf)" +map fa $fzf | { IFS= read -r sel || exit 0; lf -remote "send $id select \"$sel\""; } +map fb $sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf | { IFS= read -r d || exit 0; case "$d" in "~"*) d="$HOME${d#?}";; esac; lf -remote "send $id cd \"$d\""; } map fD zi -map fd $lf -remote "send $id select \"$(find . -type d | fzf)\"" -map ff $lf -remote "send $id select \"$(find . -type f | fzf)\"" +map fd $find . -type d | fzf | { IFS= read -r sel || exit 0; lf -remote "send $id select \"$sel\""; } +map ff $find . -type f | fzf | { IFS= read -r sel || exit 0; lf -remote "send $id select \"$sel\""; } map fm fm map gl follow_link map gc git-root diff --git a/ar/.local/bin/ccv b/ar/.local/bin/ccv index a921b9b..1ff8807 100755 --- a/ar/.local/bin/ccv +++ b/ar/.local/bin/ccv @@ -13,7 +13,11 @@ Usage: ${prog} -h | --help Concat (default mode): - Combines all files matching '<base>*.<ext>' into '<base>_combine.<ext>'. + Combines all video files matching '<base>*.*' into '<base>_combine.<ext>'. + Mixed container extensions (e.g. .mp4 + .mkv) are allowed; the output + then uses .mkv. Streams are checked with ffprobe first: all files must + share the same video codec/resolution and audio codec/rate/channels. + Previous '*_combine.*' outputs are excluded from matching. Examples: ${prog} clip_cut.mp4 ${prog} -j clip_cut.mp4 -o joined.mp4 @@ -46,6 +50,27 @@ die() { require_ffmpeg() { command -v ffmpeg >/dev/null 2>&1 || die "ffmpeg not found in PATH" + command -v ffprobe >/dev/null 2>&1 || die "ffprobe not found in PATH" +} + +# Extensions eligible for concat matching; keeps sidecar files +# (.srt, .txt, ...) out of the glob results. +is_video_ext() { + case "$1" in + mp4|mkv|webm|mov|avi|ts|m2ts|flv|wmv|m4v) return 0 ;; + *) return 1 ;; + esac +} + +# stream_sig <file> +# Prints a comparable signature of the first video/audio streams. +# Files must share a signature to be concat-able with -c copy. +stream_sig() { + _v=$(ffprobe -v error -select_streams v:0 \ + -show_entries stream=codec_name,width,height -of csv=p=0 "$1") || return 1 + _a=$(ffprobe -v error -select_streams a:0 \ + -show_entries stream=codec_name,sample_rate,channels -of csv=p=0 "$1") || return 1 + printf 'video=%s audio=%s' "$_v" "$_a" } # Globals set by resolve_output (avoids subshell variable loss): @@ -105,11 +130,28 @@ cmd_concat() { [ "$pattern" != "$input_file" ] || die "input file must have an extension: $input_file" set +e - set -- "${pattern}"*."${extension}" + set -- "${pattern}"*.* set -e # Unmatched glob remains literal in POSIX sh; check via -e on the first entry. if [ ! -e "$1" ]; then - die "no files match '${pattern}*.${extension}'" + die "no files match '${pattern}*.*'" + fi + + # Rotate args: keep only video files, dropping previous combine outputs. + i=$# + while [ "$i" -gt 0 ]; do + candidate="$1" + shift + i=$((i - 1)) + case "$candidate" in + *_combine.*|*_combine_[0-9]*.*) continue ;; + esac + is_video_ext "${candidate##*.}" || continue + set -- "$@" "$candidate" + done + + if [ $# -eq 0 ]; then + die "no video files match '${pattern}*.*'" fi if [ $# -eq 1 ]; then printf '%s: warning: only one file matches (%s); nothing to concat\n' \ @@ -117,19 +159,59 @@ cmd_concat() { exit 1 fi + # Mixed container extensions break the concat demuxer's timestamp + # offsetting even with identical codecs, so non-mkv inputs are first + # remuxed (lossless stream copy) into the one container that holds + # anything: mkv. The output then uses mkv too. + mixed="" + output_ext="$extension" + for video do + if [ "${video##*.}" != "$extension" ]; then + mixed=1 + output_ext="mkv" + break + fi + done + + # Refuse mismatched streams up front; -c copy would produce a broken + # file instead of erroring. + ref_sig="" + ref_file="" + for video do + sig=$(stream_sig "$video") || die "ffprobe failed on: $video" + if [ -z "$ref_sig" ]; then + ref_sig="$sig" + ref_file="$video" + elif [ "$sig" != "$ref_sig" ]; then + die "stream mismatch, cannot concat with stream copy: + $ref_file: $ref_sig + $video: $sig" + fi + done + if [ -n "$user_output" ]; then - resolve_output "$user_output" "$extension" + resolve_output "$user_output" "$output_ext" output_file="$RESOLVED_OUTPUT" else - output_file="${pattern}_combine.${extension}" + output_file="${pattern}_combine.${output_ext}" FF_OVERWRITE="" fi file_list=$(mktemp) - trap 'rm -f "$file_list"' EXIT INT HUP TERM + remux_dir="" + [ -n "$mixed" ] && remux_dir=$(mktemp -d) + trap 'rm -rf "$file_list" ${remux_dir:+"$remux_dir"}' EXIT INT HUP TERM + n=0 for video do - full_path=$(realpath "$video") + n=$((n + 1)) + if [ -n "$mixed" ] && [ "${video##*.}" != "mkv" ]; then + printf '%s: remuxing %s -> mkv for concat\n' "$prog" "$video" >&2 + full_path="$remux_dir/$(printf '%03d' "$n").mkv" + ffmpeg -hide_banner -v error -i "$video" -c copy "$full_path" + else + full_path=$(realpath "$video") + fi # concat demuxer: escape single quotes by closing/reopening. escaped=$(printf '%s' "$full_path" | sed "s/'/'\\\\''/g") printf "file '%s'\n" "$escaped" >>"$file_list" |
