Compare commits

..
26 Commits
Author SHA1 Message Date
Honney OC d2b11f7e5c fix: dest folder failsave 2026-09-18 18:38:00 +00:00
Honney OC 5cfbb620fb fix: rscp can now handle *wildcards and remote to remote 2026-09-18 18:33:53 +00:00
Hannes 60bf635a0c feat: add rscp function for rsyncing files to NAS datasets 2026-09-18 19:50:18 +02:00
Hannes 8b8be02912 some fixes 2026-08-31 21:36:32 +02:00
Hannes 6c746797e9 feat: add mkdir alias to configs/alias_useful.fish that cds into the created folder 2026-08-27 00:15:37 +02:00
Hannes 8edee10703 fix: refactor pacman alias to have default --needed in -S subcommand 2026-08-27 00:13:24 +02:00
Hannes ae6b0b227b fixing usage in other scripts 2026-08-25 23:58:46 +02:00
Your Name 444ca8c57d fix: robust AUR update detection in updateall
- replace fragile quoted test -z "$aur_qu" with count-based empty check for fish list handling
- separate success (code 0 + empty) vs error (code !=0 + empty) to avoid false up-to-date on network failures
- use string match -qr with explicit patterns for helpers messages instead of quoted glob checks
- fix global leak: use set -l answer and read -l, validate with string match -qr ^[Yy]$
- deduplicate and clarify error vs pending branches while keeping mandatory PKGBUILD review guard
2026-08-25 14:29:10 +00:00
Your Name e12d3d42cb fix: robust flatpak timeout handling in updateall
- wrap flatpak remote-ls check in timeout 5s with mktemp caching and proper exit code handling (124 = timeout)
- fix inverted -n/-z logic and uninitialized flatpak_has_updates causing Missing argument error
- distinguish timeout vs generic check failure with clear messages
- add timeout 300s guard to flatpak update and handle 124 as update timed out
- gracefully degrade when timeout binary missing instead of skipping flatpak entirely
- quote temp file paths and handle mktemp failure reliably
2026-08-25 14:27:20 +00:00
Hannes deb879b6c4 fix: Improve flatpak update check logic 2026-08-24 14:07:09 +02:00
Hannes 7a1e432231 fix: update flatpak update check to handle timeouts and null output 2026-08-24 13:55:06 +02:00
Hannes f1fb649e98 refactor: Moved updateall and added some lines to clearyfy in arch_config.fish 2026-08-23 20:24:26 +02:00
Hannes 1f17b19f1e refactor: Improve umount and force_unmount functions for better error handling and output formatting 2026-08-22 23:57:13 +02:00
Hannes 3305f5a543 feat: Update updateall script
Updated updateall to include comprehensive test coverage, support for Vencord, and improved output formatting.
2026-08-22 23:13:18 +02:00
Hannes f88dbcc6f4 added hypridle-reload 2026-08-22 22:01:15 +02:00
Hannes 65c3034b91 added fish greeting 2026-08-22 16:21:10 +02:00
Hannes 485d8768f9 updateall also runs matugen updates 2026-08-22 15:42:06 +02:00
Hannes 275121a638 added -r as standard to rm 2026-08-21 22:28:17 +02:00
Hannes 65ebd5e171 added a function to easily generate ssh key 2026-08-21 21:14:43 +02:00
Hannes 9ed74e1028 added igrep for inverse grep 2026-08-21 19:47:34 +02:00
Hannes a3f0b42353 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-08-20 17:46:01 +02:00
Hannes 318420eba6 fixes to mount scripts 2026-08-20 17:45:44 +02:00
Honney 995f03b9bd fixed missspelling 2026-08-20 02:37:13 +02:00
Hannes e6785a24a7 updates 2026-08-19 23:31:01 +02:00
Hannes 95183069ce some additions 2026-08-14 13:39:41 +02:00
Hannes dd0bc6a77c added other mounts 2026-08-13 16:57:18 +02:00
12 changed files with 1629 additions and 172 deletions
+4
View File
@@ -0,0 +1,4 @@
complete -c copytime -f -a '(__fish_complete_path)' -d 'Source file'
complete -c copytime -f -a '(__fish_complete_path)' -d 'Destination file'
complete -c copytime -s d -l date -x -d 'Set container creation date directly (e.g. 2020-01-02 03:04:05)'
complete -c copytime -s h -l help -d 'Show help'
+5
View File
@@ -0,0 +1,5 @@
complete -c vrot -f -a '(__fish_complete_suffix .mp4 .mkv .mov .m4v .webm .avi .ts .mts .m2ts .flv .wmv .mpg .mpeg .vob .3gp)' -d 'Video file'
complete -c vrot -s h -l help -d 'Show help'
complete -c vrot -s r -l reencode -d 'Re-encode the video (rotate pixels, works everywhere)'
complete -c vrot -s a -l angle -x -a '90 180 270' -d 'Rotation angle (degrees clockwise)'
complete -c vrot -s p -l preset -x -a 'ultrafast superfast veryfast faster fast medium slow slower veryslow' -d 'x264/x265 encoder preset'
-4
View File
@@ -52,8 +52,4 @@ if status is-interactive
source $HOME/.config/fish/configs/default_config.fish source $HOME/.config/fish/configs/default_config.fish
end end
end end
if test -e /usr/bin/fastfetch
fastfetch
end
end end
+17 -3
View File
@@ -3,9 +3,16 @@
# #
alias mount_all='sudo $HOME/.config/fish/scripts/mount.sh' alias mount_all='sudo $HOME/.config/fish/scripts/mount.sh'
alias umount_all='sudo $HOME/.config/fish/scripts/umount.sh'
function mkdir
command mkdir $argv
and cd -- $argv[-1]
end
################ COMMON ALIASES ################################################ ################ COMMON ALIASES ################################################
alias rm='rm -r'
alias remount='sudo mount -a' alias remount='sudo mount -a'
alias mount_config='sudo nano /etc/fstab' alias mount_config='sudo nano /etc/fstab'
alias own='sudo chown -R "$USER":"$USER"' alias own='sudo chown -R "$USER":"$USER"'
@@ -71,6 +78,7 @@ if test -e /usr/bin/nano
echo "Usage: nanorm {FILE}" echo "Usage: nanorm {FILE}"
return 1 return 1
end end
rm $argv[1]
nano $argv[1] nano $argv[1]
end end
else else
@@ -274,9 +282,9 @@ end
if test -e /usr/bin/mpv if test -e /usr/bin/mpv
alias uni_play='mpv --vo=tct' alias uni_play='mpv --vo=tct'
alias asci_play='mpv --vo=caca' alias ascii_play='mpv --vo=caca'
else else
for cmd in uni_play asci_play for cmd in uni_play ascii_play
function $cmd --inherit-variable cmd function $cmd --inherit-variable cmd
echo "The command 'mpv' is not installed. Please install mpv to use this: https://github.com/mpv-player/mpv" echo "The command 'mpv' is not installed. Please install mpv to use this: https://github.com/mpv-player/mpv"
end end
@@ -285,7 +293,7 @@ end
################ GREP ######################################################### ################ GREP #########################################################
if test -e /usr/bin/ugrep if command -q ugrep
alias grep='ugrep --color=auto' alias grep='ugrep --color=auto'
alias egrep='ugrep -E --color=auto' alias egrep='ugrep -E --color=auto'
alias fgrep='ugrep -F --color=auto' alias fgrep='ugrep -F --color=auto'
@@ -294,6 +302,12 @@ else
alias fgrep='grep -F' alias fgrep='grep -F'
end end
if command -q ugrep
alias igrep='ugrep --color=auto --invert-match'
else if command -q grep
alias igrep='grep --color=auto --invert-match'
end
################ WGET ######################################################### ################ WGET #########################################################
if test -e /usr/bin/wget if test -e /usr/bin/wget
+583 -116
View File
@@ -4,123 +4,20 @@
source $HOME/.config/fish/configs/uni.fish source $HOME/.config/fish/configs/uni.fish
function get_pkg_version # ------------------------------------------------------------------------------
set pkg $argv[1] # Aliases & small utilities (kept after main for readability)
# ------------------------------------------------------------------------------
if pacman -Q $pkg >/dev/null 2>&1
pacman -Q $pkg
else
echo ""
end
end
function kernel_to_pkg
set kernel (uname -r)
if string match -q "*zen*" $kernel
echo linux-zen
else if string match -q "*lts*" $kernel
echo linux-lts
else if string match -q "*hardened*" $kernel
echo linux-hardened
else
echo linux
end
end
function updateall
######## Get current versions (if installed)
if command -q discord
set discord_version (get_pkg_version discord)
end
set kernel_version (get_pkg_version (kernel_to_pkg))
######## Run PACMAN updates
set_color cyan
echo "#### Updating pacman ####"
set_color normal
sudo pacman -Syu
######## Do additional Discord Updates
if command -q discord; and test "$discord_version" != "$(get_pkg_version discord)"
set_color cyan
echo "Discord version changed: $discord_version -> $(get_pkg_version discord)"
set_color normal
if test -e /usr/bin/curl
echo "Running Vencord installer..."
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
else
echo "'curl' is not installed. Install it to update Discord plugins."
end
end
######## Run FLATPAK Updates
if test -e /usr/bin/flatpak
set_color cyan
echo "#### Updating flatpak ####"
set_color normal
flatpak update
end
######## Run GIT Updates
set_color cyan
echo "#### Updating quickshell ####"
set_color normal
if test -d ~/.config/quickshell && test -d ~/.config/quickshell/.git
pushd ~/.config/quickshell/
git pull
popd
end
set_color cyan
echo "#### Updating fish ####"
set_color normal
if test -d ~/.config/fish && test -d ~/.config/fish/.git
pushd ~/.config/fish/
git pull
popd
end
set_color cyan
echo "#### Updating hyprland ####"
set_color normal
if test -d ~/.config/hypr && test -d ~/.config/hypr/.git
pushd ~/.config/hypr/
git pull
popd
end
######## Run AUR Updates
set_color cyan
echo "#### Updating AUR ####"
set_color normal
if test -e /usr/bin/paru
paru -Sua --sudoloop
else if test -e /usr/bin/yay
yay -Sua --sudoloop
end
######## Restart if Kernel Updated
if test "$kernel_version" != "$(get_pkg_version $(kernel_to_pkg))"
set_color cyan
echo "Kernel changed: $kernel_version -> $(get_pkg_version $(kernel_to_pkg))"
read -P "Reboot now? [y/N]: " answer
set_color normal
if test "$answer" = "y" -o "$answer" = "Y"
reboot
else
echo "Skipping reboot."
end
end
end
alias fixpacman='sudo rm -f /var/lib/pacman/db.lck' alias fixpacman='sudo rm -f /var/lib/pacman/db.lck'
function pacman
if test "$argv[1]" = "-S"
command pacman -S --needed $argv[2..]
else
command pacman $argv
end
end
if test -e /usr/bin/expac if test -e /usr/bin/expac
alias rip='expac --timefmt="%Y-%m-%d %T" "%l\t%n %v" | sort | tail -200 | nl' alias rip='expac --timefmt="%Y-%m-%d %T" "%l\t%n %v" | sort | tail -200 | nl'
alias big='expac -H M "%m\t%n" | sort -h | nl' alias big='expac -H M "%m\t%n" | sort -h | nl'
@@ -146,17 +43,28 @@ end
if test -e /usr/bin/tmux if test -e /usr/bin/tmux
function quickshell-reload function quickshell-reload
if test -e /usr/bin/quickshell if command -q quickshell
tmux kill-session -t qs 2>/dev/null tmux kill-session -t qs 2>/dev/null
tmux new-session -d -s qs 'quickshell' tmux new-session -d -s qs 'env QT_QPA_PLATFORMTHEME=qt6ct quickshell'
else else
echo "'quickshell' is not installed. Install it via your package manager." echo "'quickshell' is not installed. Install it via your package manager."
end end
end end
function hypridle-reload
if command -q hypridle
tmux kill-session -t hypridle 2>/dev/null
tmux new-session -d -s hypridle 'hypridle'
else
echo "'hypridle' is not installed. Install it via your package manager."
end
end
else else
function quickshell-reload function quickshell-reload
echo "'tmux' is not installed. Install it via your package manager." echo "'tmux' is not installed. Install it via your package manager."
end end
function hypridle-reload
echo "'tmux' is not installed. Install it via your package manager."
end
end end
if test -e /usr/bin/reflector if test -e /usr/bin/reflector
@@ -165,3 +73,562 @@ if test -e /usr/bin/reflector
alias mirrord='sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist' alias mirrord='sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist'
alias mirrors='sudo reflector --latest 50 --number 20 --sort score --save /etc/pacman.d/mirrorlist' alias mirrors='sudo reflector --latest 50 --number 20 --sort score --save /etc/pacman.d/mirrorlist'
end end
function pacman-autoremove
set -l orphans (pacman -Qtdq)
if test (count $orphans) -gt 0
sudo pacman -Rns $orphans
else
echo "No orphaned packages."
end
end
# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------
function get_pkg_version
set pkg $argv[1]
if pacman -Q $pkg >/dev/null 2>&1
pacman -Q $pkg
else
echo ""
end
end
function kernel_to_pkg
set kernel (uname -r)
if string match -q "*zen*" $kernel
echo linux-zen
else if string match -q "*lts*" $kernel
echo linux-lts
else if string match -q "*hardened*" $kernel
echo linux-hardened
else
echo linux
end
end
# Print a colored section header (cyan)
function _print_section
set -l title $argv[1]
set_color cyan
echo "#### $title ####"
set_color normal
end
# ------------------------------------------------------------------------------
# Main: updateall
# Orchestrates system + dotfiles updates with:
# - suppression when up-to-date (short "up to date" line)
# - full output when updates exist (do NOT suppress)
# - per-component summary at the end (git ones are important)
# - --vencord / -v flag gates all discord/vencord queries
# - AUR diff is mandatory (cannot be skipped)
#
# Order (readability):
# 1) Flags / summary init / version snapshot
# 2) System packages: pacman -> AUR -> flatpak
# 3) Dotfiles: git (quickshell/fish/hypr/matugen)
# 4) Optional: discord/vencord (only if --vencord)
# 5) Kernel reboot prompt
# 6) Summary
# ------------------------------------------------------------------------------
function updateall
# ---- 1) Flags ----
set -l _do_vencord 0
argparse --name=updateall 'v/vencord' 'h/help' -- $argv
or return 1
if set -q _flag_help
echo "Usage: updateall [--vencord] [-h/--help]"
echo " --vencord, -v also (re)install/update Vencord when Discord changes or force when up to date"
echo " -h, --help show this help"
return 0
end
if set -q _flag_vencord
set _do_vencord 1
end
if test (count $argv) -gt 0
echo "updateall: unknown argument: $argv" >&2
return 1
end
# Summary tracking - parallel arrays: labels / status / color
set -l _labels
set -l _status
set -l _colors
# Version snapshot (discord only if --vencord, per request)
set -l discord_version ""
if test $_do_vencord -eq 1; and type -q discord
set discord_version (get_pkg_version discord)
end
set -l kernel_version (get_pkg_version (kernel_to_pkg))
# ----------------------------------------------------------------------
# 2) System packages
# ----------------------------------------------------------------------
# ---- pacman (core) ----
_print_section "Updating pacman"
set -l pacman_status "skipped"
set -l pacman_color yellow
if type -q pacman
set -l has_updates 1
set -l qu_output ""
if type -q checkupdates
set qu_output (checkupdates 2>&1)
if test $status -eq 0 -a -n "$qu_output"
set has_updates 0
else if string match -q "*ERROR*Failed to synchronize*" "$qu_output"
set has_updates 0
end
else
set qu_output (pacman -Qu 2>&1)
if test $status -eq 0
set has_updates 0
else if string match -q "*database*" "$qu_output"
set has_updates 0
end
end
if test $has_updates -eq 1
echo "pacman: up to date"
set pacman_status "up to date"
set pacman_color green
else
if test -n "$qu_output"
echo "Pending pacman updates:"
printf "%s\n" $qu_output
end
sudo pacman -Syu
set -l pacman_code $status
if test $pacman_code -eq 0
set pacman_status "updated"
set pacman_color green
else
set pacman_status "failed ($pacman_code)"
set pacman_color red
end
end
else
echo "pacman not found, skipping"
set pacman_status "not installed"
set pacman_color yellow
end
set -a _labels "pacman"
set -a _status $pacman_status
set -a _colors $pacman_color
# ---- AUR (paru/yay) - directly after pacman, mandatory diff ----
_print_section "Updating AUR"
set -l aur_status "skipped"
set -l aur_color yellow
set -l aur_helper ""
if type -q paru
set aur_helper paru
else if type -q yay
set aur_helper yay
end
if test -n "$aur_helper"
set -l aur_qu ($aur_helper -Qua 2>&1)
set -l aur_qu_code $status
# Robust state detection: use (count) not quoted -z, and explicit patterns.
# aur_qu is a list (one element per line) -> count is reliable.
set -l aur_is_up_to_date 0
set -l aur_has_check_error 0
if test $aur_qu_code -eq 0
if test (count $aur_qu) -eq 0
set aur_is_up_to_date 1
else if string match -qr -- "there is nothing to do|No AUR|No packages to upgrade" $aur_qu
set aur_is_up_to_date 1
end
else
# Non-zero: only treat as up-to-date if helper explicitly says so
if string match -qr -- "there is nothing to do|No AUR" $aur_qu
set aur_is_up_to_date 1
else
set aur_has_check_error 1
end
end
if test $aur_is_up_to_date -eq 1
echo "AUR: up to date"
set aur_status "up to date"
set aur_color green
else if test $aur_has_check_error -eq 1
# Real check failure: do NOT silently report up-to-date
echo "Failed to check for AUR updates (code $aur_qu_code):"
if test (count $aur_qu) -gt 0
printf "%s\n" $aur_qu
else
echo "(no output)"
end
echo ""
set_color yellow
echo "==> AUR PKGBUILD review is MANDATORY - diff cannot be skipped."
echo " Note: PKGBUILDs must NEVER contain 'sudo'. Please verify diffs contain no 'sudo'."
set_color normal
set -l answer ""
read -l -P "Update now? [y/N]: " answer
if string match -qr -- "^[Yy]\$" "$answer"
if test "$aur_helper" = "paru"
paru -Sua --sudoloop --review
else
yay -Sua --sudoloop --diffmenu --answerdiff All --answerclean All
end
set -l _aur_code $status
if test $_aur_code -eq 0
set aur_status "updated"
set aur_color green
else
set aur_status "failed ($_aur_code)"
set aur_color red
end
end
else
echo "Pending AUR updates:"
printf "%s\n" $aur_qu
set_color yellow
echo "==> AUR PKGBUILD review is MANDATORY - diff cannot be skipped."
echo " Note: PKGBUILDs must NEVER contain 'sudo'. Please verify diffs contain no 'sudo'."
set_color normal
set -l answer ""
read -l -P "Update now? [y/N]: " answer
if string match -qr -- "^[Yy]\$" "$answer"
if test "$aur_helper" = "paru"
paru -Sua --sudoloop --review
else
yay -Sua --sudoloop --diffmenu --answerdiff All --answerclean All
end
set -l _aur_code $status
if test $_aur_code -eq 0
set aur_status "updated"
set aur_color green
else
set aur_status "failed ($_aur_code)"
set aur_color red
end
end
end
else
echo "No AUR helper (paru/yay) found, skipping"
set aur_status "no helper"
set aur_color yellow
end
set -a _labels "AUR"
set -a _status $aur_status
set -a _colors $aur_color
# ---- flatpak ----
_print_section "Updating flatpak"
set -l flatpak_status "skipped"
set -l flatpak_color yellow
if not type -q flatpak
set flatpak_status "not installed"
set flatpak_color yellow
else
set -l flatpak_tmp (mktemp)
if test $status -ne 0 -o -z "$flatpak_tmp"
echo "flatpak: failed to create temp file"
set flatpak_status "update check failed"
set flatpak_color red
else
set -l flatpak_check_code
set -l flatpak_check
if type -q timeout
timeout 5s flatpak remote-ls --updates >"$flatpak_tmp" 2>&1
set flatpak_check_code $status
else
flatpak remote-ls --updates >"$flatpak_tmp" 2>&1
set flatpak_check_code $status
end
set flatpak_check (cat "$flatpak_tmp")
rm -f "$flatpak_tmp"
# flatpak_has_updates: 0 = pending updates, 1 = up to date, 2 = check failed/timeout
set -l flatpak_has_updates 0
if test $flatpak_check_code -eq 0
if test -z "$flatpak_check"
set flatpak_has_updates 1
else
set flatpak_has_updates 0
end
else if test $flatpak_check_code -eq 124
set flatpak_has_updates 2
else
set flatpak_has_updates 2
end
if test $flatpak_has_updates -eq 2
if test $flatpak_check_code -eq 124
echo "flatpak: update check timed out (5s)"
else
echo "flatpak: update check failed"
end
if test -n "$flatpak_check"
printf "%s\n" $flatpak_check
end
set flatpak_status "update check failed"
set flatpak_color red
else if test $flatpak_has_updates -eq 1
echo "flatpak: up to date"
set flatpak_status "up to date"
set flatpak_color green
else
if test -n "$flatpak_check"
echo "Pending flatpak updates:"
printf "%s\n" $flatpak_check
end
set -l flatpak_code
if type -q timeout
timeout 300s flatpak update
set flatpak_code $status
else
flatpak update
set flatpak_code $status
end
if test $flatpak_code -eq 124
echo "flatpak: update timed out (300s)"
set flatpak_status "update timed out"
set flatpak_color red
else if test $flatpak_code -eq 0
set flatpak_status "updated"
set flatpak_color green
else
set flatpak_status "failed ($flatpak_code)"
set flatpak_color red
end
end
end
end
set -a _labels "flatpak"
set -a _status $flatpak_status
set -a _colors $flatpak_color
# ----------------------------------------------------------------------
# 3) Dotfiles (git) - always show per-repo success/fail, suppress only when up to date
# ----------------------------------------------------------------------
set -l git_repos "quickshell:$HOME/.config/quickshell" "fish:$HOME/.config/fish" "hypr:$HOME/.config/hypr" "matugen:$HOME/.config/matugen"
if not type -q git
echo "git not installed"
set git_status "git not installed"
set git_color yellow
set -a _labels "git"
set -a _status $git_status
set -a _colors $git_color
else
for entry in $git_repos
set -l parts (string split ":" -- $entry)
set -l name $parts[1]
set -l path $parts[2]
_print_section "Updating $name"
set -l git_status "skipped"
set -l git_color yellow
if not test -d $path/.git
echo "skipped: $path not a git repo"
set git_status "not tracked"
set git_color yellow
else
git -C $path fetch --quiet >/dev/null 2>&1
set -l fetch_code $status
set -l behind_str (git -C $path rev-list --count HEAD..@{u} 2>&1)
set -l behind_code $status
if test $fetch_code -ne 0 -o $behind_code -ne 0
set -l git_output (git -C $path pull 2>&1)
set -l git_code $status
if test $git_code -ne 0
printf "%s\n" $git_output
set git_status "failed ($git_code)"
set git_color red
else if string match -q "*Already up to date*" "$git_output"
echo "$name: up to date"
set git_status "up to date"
set git_color green
else
printf "%s\n" $git_output
set git_status "updated"
set git_color green
end
else if test "$behind_str" = "0"
echo "$name: up to date"
set git_status "up to date"
set git_color green
else
git -C $path pull
set -l pull_code $status
if test $pull_code -eq 0
set git_status "updated"
set git_color green
else
set git_status "failed ($pull_code)"
set git_color red
end
end
end
set -a _labels "git:$name"
set -a _status $git_status
set -a _colors $git_color
end
end
# ----------------------------------------------------------------------
# 4) Optional: Discord / Vencord (only when --vencord)
# ----------------------------------------------------------------------
set -l discord_status "skipped"
set -l discord_color yellow
set -l vencord_status "skipped"
set -l vencord_color yellow
set -l _need_vencord_label 0
if test $_do_vencord -eq 0
set discord_status "skipped (use --vencord)"
set discord_color yellow
set vencord_status "skipped (use --vencord)"
set vencord_color yellow
else if type -q discord
set -l new_discord_version (get_pkg_version discord)
if test "$discord_version" != "$new_discord_version"
set_color cyan
echo "Discord version changed: $discord_version -> $new_discord_version"
set_color normal
set discord_status "updated ($new_discord_version)"
set discord_color green
if test $_do_vencord -eq 1
set _need_vencord_label 1
if type -q curl
echo "Running Vencord installer (--vencord)..."
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
if test $status -eq 0
set vencord_status "updated ($new_discord_version)"
set vencord_color green
set discord_status "$discord_status + vencord ok"
else
set vencord_status "failed ($status)"
set vencord_color red
set discord_status "$discord_status + vencord failed"
set discord_color red
end
else
echo "'curl' is not installed. Install it to update Discord plugins."
set vencord_status "curl missing"
set vencord_color yellow
set discord_status "$discord_status + vencord skipped (curl missing)"
set discord_color yellow
end
else
set vencord_status "skipped (discord updated, use --vencord)"
set vencord_color yellow
echo "Discord updated, skipping Vencord (use --vencord to update)"
end
else
set discord_status "up to date ($new_discord_version)"
set discord_color green
if test $_do_vencord -eq 1
set _need_vencord_label 1
set_color cyan
echo "Discord up to date ($new_discord_version), but --vencord given: running Vencord installer..."
set_color normal
if type -q curl
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
if test $status -eq 0
set vencord_status "refreshed/updated"
set vencord_color green
set discord_status "$discord_status + vencord ok"
else
set vencord_status "failed ($status)"
set vencord_color red
set discord_status "$discord_status + vencord failed"
end
else
echo "'curl' is not installed. Install it to update Discord plugins."
set vencord_status "curl missing"
set vencord_color yellow
end
else
set vencord_status "skipped (use --vencord)"
set vencord_color yellow
end
end
else
set discord_status "not installed"
set discord_color yellow
if test $_do_vencord -eq 1
set _need_vencord_label 1
set vencord_status "skipped (discord not installed)"
set vencord_color yellow
echo "Discord not installed, skipping Vencord"
end
end
set -a _labels "discord"
set -a _status $discord_status
set -a _colors $discord_color
if test $_do_vencord -eq 1
set -a _labels "vencord"
set -a _status $vencord_status
set -a _colors $vencord_color
end
# ----------------------------------------------------------------------
# 5) Kernel (needs reboot if package changed)
# ----------------------------------------------------------------------
set -l kernel_status "up to date"
set -l kernel_color green
set -l new_kernel_version (get_pkg_version (kernel_to_pkg))
if test "$kernel_version" != "$new_kernel_version"
set_color cyan
echo "Kernel changed: $kernel_version -> $new_kernel_version"
set_color normal
set kernel_status "updated ($kernel_version -> $new_kernel_version)"
set kernel_color green
set answer ""
read -P "Reboot now? [y/N]: " answer
if test "$answer" = "y" -o "$answer" = "Y"
reboot
else
echo "Skipping reboot."
set kernel_status "$kernel_status (reboot skipped)"
end
else
set kernel_status "up to date ($new_kernel_version)"
set kernel_color green
end
set -a _labels "kernel"
set -a _status $kernel_status
set -a _colors $kernel_color
# ----------------------------------------------------------------------
# 6) Summary (always shown, per-component success/fail)
# ----------------------------------------------------------------------
echo ""
set_color --bold cyan
echo "########################"
echo "#### Update Summary ####"
echo "########################"
set_color normal
set -l max_len 0
for l in $_labels
if test (string length -- $l) -gt $max_len
set max_len (string length -- $l)
end
end
for i in (seq (count $_labels))
set -l label $_labels[$i]
set -l stat $_status[$i]
set -l col $_colors[$i]
set -l pad (string repeat -n (math $max_len - (string length -- $label)) " ")
set_color normal
printf "%s%s : " $label $pad
set_color $col
echo $stat
set_color normal
end
end
+267
View File
@@ -0,0 +1,267 @@
function copytime -d 'Copy timestamps between files; for media files also copies the container creation date'
argparse -n copytime 'h/help' 'd/date=' -- $argv
or return 2
if set -q _flag_help
__copytime_usage
return 0
end
if test (count $argv) -lt 1
__copytime_usage
return 2
end
__copytime_colors
if set -q _flag_date
set -l rc 0
for f in $argv
__copytime_setdate "$f" "$_flag_date"
or set rc 1
end
return $rc
end
if test (count $argv) -lt 2
__copytime_usage
return 2
end
set -l src $argv[1]
set -l dsts $argv[2..-1]
if not test -e "$src"
__copytime_error "no such source: '$src'"
return 1
end
switch (uname -s)
case Linux
__copytime_linux "$src" $dsts
case Darwin
__copytime_darwin "$src" $dsts
case '*'
__copytime_error "unsupported platform '(uname -s)'"
return 1
end
end
function __copytime_linux
set -l src $argv[1]
set -l rc 0
set -l mtime (stat -c '%y' -- "$src" | string replace -r '\.[0-9]+' '')
set -l atime (stat -c '%x' -- "$src" | string replace -r '\.[0-9]+' '')
echo "$vrot_c_dim source: $src$vrot_c_reset"
echo "$vrot_c_dim modified: $mtime$vrot_c_reset"
echo "$vrot_c_dim accessed: $atime$vrot_c_reset"
set -l birth (stat -c '%w' -- "$src")
if test -n "$birth"; and string match -q '*[-Unknown]*' "$birth"
set birth ''
end
if test -n "$birth"
set -l btime (string replace -r '\.[0-9]+' '' -- "$birth")
echo "$vrot_c_dim created: $btime (filesystem creation time cannot be set on Linux)$vrot_c_reset"
end
set -l created (__copytime_mediadate "$src")
if test -n "$created"
set -l ctime (string replace 'T' ' ' -- "$created" | string replace -r '\.\d+Z?$' '')
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
end
for dst in $argv[2..-1]
if not test -e "$dst"
__copytime_error "skipping missing destination: '$dst'"
set rc 1
continue
end
touch -a -m -r "$src" "$dst"
if test $status -ne 0
__copytime_error "failed to copy timestamps to '$dst'"
set rc 1
continue
end
set -l dm (stat -c '%y' -- "$dst" | string replace -r '\.[0-9]+' '')
echo "$vrot_c_ok$dst$vrot_c_dim ← modified $dm$vrot_c_reset"
if test -n "$created"
__copytime_meta "$dst" "$created"
or set rc 1
end
end
return $rc
end
function __copytime_darwin
set -l src $argv[1]
set -l rc 0
set -l mtime (stat -f '%Sm' -t '%Y-%m-%d %H:%M:%S' -- "$src")
set -l btime (stat -f '%SB' -t '%Y-%m-%d %H:%M:%S' -- "$src")
echo "$vrot_c_dim source: $src$vrot_c_reset"
echo "$vrot_c_dim modified: $mtime$vrot_c_reset"
echo "$vrot_c_dim created: $btime$vrot_c_reset"
set -l created (__copytime_mediadate "$src")
if test -n "$created"
set -l ctime (string replace 'T' ' ' -- "$created" | string replace -r '\.\d+Z?$' '')
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
end
set -l birth (stat -f '%SB' -t '%m/%d/%Y %H:%M:%S' -- "$src")
for dst in $argv[2..-1]
if not test -e "$dst"
__copytime_error "skipping missing destination: '$dst'"
set rc 1
continue
end
touch -a -m -r "$src" "$dst"
if test $status -ne 0
set rc 1
continue
end
if command -q SetFile
SetFile -d "$birth" "$dst"
if test $status -ne 0
__copytime_error "failed to set creation time on '$dst'"
set rc 1
end
else
echo "$vrot_c_warn ⚠ SetFile not found — creation time not copied to $dst$vrot_c_reset" >&2
end
set -l db (stat -f '%SB' -t '%Y-%m-%d %H:%M:%S' -- "$dst")
echo "$vrot_c_ok$dst$vrot_c_dim ← created $db$vrot_c_reset"
if test -n "$created"
__copytime_meta "$dst" "$created"
or set rc 1
end
end
return $rc
end
function __copytime_mediadate
if not command -q ffprobe
return 0
end
if not __copytime_media "$argv[1]"
return 0
end
set -l d (ffprobe -v error -show_entries format_tags=creation_time \
-of default=noprint_wrappers=1:nokey=1 "$argv[1]")[1]
string match -rq '^[0-9]{4}-[0-9]{2}-[0-9]{2}' "$d"; and echo "$d"
end
function __copytime_meta
set -l dst $argv[1]
set -l date $argv[2]
if not command -q ffmpeg
return 0
end
if not __copytime_media "$dst"
return 0
end
set -l tmp (string join '' "$dst" .ct. (random) (path extension "$dst"))
ffmpeg -hide_banner -loglevel error -y -i "$dst" -map 0 -map '-0:d' -map '-0:t' \
-c copy -metadata creation_time="$date" "$tmp"
if test $status -ne 0
rm -f "$tmp"
__copytime_error "failed to copy container creation date to '$dst'"
return 1
end
mv -f -- "$tmp" "$dst"
if test $status -ne 0
rm -f "$tmp"
__copytime_error "failed to replace '$dst'"
return 1
end
set -l ctime (string replace 'T' ' ' -- "$date" | string replace -r '\.\d+Z?$' '')
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
end
function __copytime_setdate
set -l file $argv[1]
set -l date $argv[2]
if not test -e "$file"
__copytime_error "no such file: '$file'"
return 1
end
if not __copytime_media "$file"
__copytime_error "'$file' is not a supported media file"
return 1
end
if not command -q ffmpeg
__copytime_error "ffmpeg is required to set container dates"
return 1
end
set -l tmp (string join '' "$file" .ct. (random) (path extension "$file"))
ffmpeg -hide_banner -loglevel error -y -i "$file" -map 0 -map '-0:d' -map '-0:t' \
-c copy -metadata creation_time="$date" "$tmp"
if test $status -ne 0
rm -f "$tmp"
__copytime_error "failed to write creation date to '$file'"
return 1
end
mv -f -- "$tmp" "$file"
if test $status -ne 0
rm -f "$tmp"
__copytime_error "failed to replace '$file'"
return 1
end
set -l dsp (string replace 'T' ' ' -- "$date")
echo "$vrot_c_ok$file$vrot_c_dim ← container creation date $dsp$vrot_c_reset"
end
function __copytime_media
set -l ext (string lower (path extension "$argv[1]"))
switch "$ext"
case '.mp4' '.mov' '.m4v' '.mkv' '.webm' '.avi' '.ts' '.mts' '.m2ts' '.flv' '.wmv' '.mpg' '.mpeg' '.3gp' '.vob' '.ogv'
return 0
end
return 1
end
function __copytime_colors
set -q vrot_colors_set; and return 0
set -g vrot_colors_set 1
if isatty stdout
set -g vrot_c_ok (set_color brgreen)
set -g vrot_c_dim (set_color brblack)
set -g vrot_c_warn (set_color bryellow)
set -g vrot_c_err (set_color brred)
set -g vrot_c_reset (set_color normal)
else
for c in ok dim warn err reset
set -g vrot_c_$c ''
end
end
end
function __copytime_error
echo "$vrot_c_err""copytime: "$argv"$vrot_c_reset" >&2
end
function __copytime_usage
echo 'usage: copytime <source> <destination> [<destination> ...]'
echo ' copytime --date <DATE> <video> [<video> ...]'
echo
echo 'Copies the access and modified timestamps from <source> to each'
echo '<destination> (same semantics as `touch -r`). On macOS the filesystem'
echo 'creation time is copied too (requires SetFile).'
echo
echo 'For media files (mp4, mkv, mov, webm, ...), the creation date stored'
echo 'inside the container - the one apps like Plex and photo managers show -'
echo 'is copied from source to destination and printed. Data/timecode tracks'
echo 'are dropped while remuxing (lossless, no re-encode).'
echo
echo 'options:'
echo ' -d, --date <DATE> set the container creation date of the given video(s)'
echo ' directly, e.g. "2020-01-02 03:04:05"'
echo ' -h, --help show this help'
end
+5
View File
@@ -0,0 +1,5 @@
function fish_greeting
if test -e /usr/bin/fastfetch
fastfetch
end
end
+313
View File
@@ -0,0 +1,313 @@
function rscp --description "Copy SOURCE... to DESTINATION via rsync (local or NAS)"
# rscp: rsync-based copy that understands the local NAS mounts.
#
# Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION
#
# Only the LAST argument is the destination; everything before it is a
# source. That way wildcards just work: `rscp *.mkv /dest/` copies every
# match instead of silently dropping all but the first one.
#
# Paths under /home/honney/mount/<dataset> are transferred directly as
# NAS:/mnt/tank/<dataset>, so rsync talks to the NAS instead of going
# through the local mount. Purely local (PC -> PC) copies use rsync with
# the same flags as rcp (-avh --progress).
# NAS -> NAS copies run on the NAS itself via `ssh <host> ... rsync`,
# keeping the flags of the "to remote" direction (sudo + chown).
set -l force 0
# Only leading flags are options; everything else (even a source starting
# with "-") is a path. Use `--` to end option parsing explicitly.
while test (count $argv) -gt 0
switch $argv[1]
case -y --yes
set force 1
set -e argv[1]
case -h --help
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION"
echo ""
echo "Copy one or more SOURCEs to DESTINATION with rsync."
echo "Only the last argument is the destination; everything before it is a source,"
echo "so wildcards at the source (e.g. rscp *.mkv /dest/) work as expected."
echo ""
echo "Options:"
echo " -y, --yes skip the overwrite confirmation prompt"
echo " -h, --help show this help"
return 0
case --
set -e argv[1]
break
case '-*'
echo "rscp: unknown option: $argv[1]" >&2
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION" >&2
return 1
case '*'
break
end
end
if test (count $argv) -lt 2
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION" >&2
return 1
end
if not command -q rsync
echo "rscp: 'rsync' is not installed. Install it via your package manager." >&2
return 1
end
# Mount <-> NAS dataset mapping (keep both lists in the same order)
set -l mounts /home/honney/mount/Media /home/honney/mount/Data /home/honney/mount/Ripping /home/honney/mount/Apps
set -l remotes NAS:/mnt/tank/Media NAS:/mnt/tank/Data NAS:/mnt/tank/Ripping NAS:/mnt/tank/Apps
# Only the last argument is the destination; everything before it is a
# source, so any number of (wildcard-expanded) sources is supported.
set -l n (count $argv)
set -l last_src (math $n - 1)
set -l dst_raw $argv[$n]
set -l srcs_raw $argv[1..$last_src]
# Translate sources: local mount path -> NAS:<path>. For each source keep
# the translated path, a 1/0 remote flag, the remote host and the path
# as seen on the remote side (without the "HOST:" prefix).
set -l srcs
set -l src_remote_flags
set -l src_hosts
set -l src_naslocals
set -l hosts
for raw in $srcs_raw
set -l s $raw
set -l is_remote 0
for i in (seq (count $mounts))
if string match -q -- $mounts[$i] $s; or string match -q -- "$mounts[$i]/*" $s
set s (string replace -f -- $mounts[$i] $remotes[$i] $s)
set is_remote 1
break
end
end
# Also accept an explicit HOST:/path given directly.
if test $is_remote -eq 0
if string match -qr '^[A-Za-z0-9_.@-]+:/' -- $s
set is_remote 1
end
end
set -l host ""
set -l naslocal $s
if test $is_remote -eq 1
set -l parts (string split -m1 : -- $s)
set host $parts[1]
set naslocal (string join : -- $parts[2..-1])
if not contains -- $host $hosts
set -a hosts $host
end
end
set -a srcs $s
set -a src_remote_flags $is_remote
set -a src_hosts $host
set -a src_naslocals $naslocal
end
# Translate the destination the same way (it is always $argv[-1]).
set -l dst $dst_raw
set -l dst_remote 0
for i in (seq (count $mounts))
if string match -q -- $mounts[$i] $dst; or string match -q -- "$mounts[$i]/*" $dst
set dst (string replace -f -- $mounts[$i] $remotes[$i] $dst)
set dst_remote 1
break
end
end
if test $dst_remote -eq 0
if string match -qr '^[A-Za-z0-9_.@-]+:/' -- $dst
set dst_remote 1
end
end
set -l dst_host ""
set -l dst_naslocal $dst
if test $dst_remote -eq 1
set -l dparts (string split -m1 : -- $dst)
set dst_host $dparts[1]
set dst_naslocal (string join : -- $dparts[2..-1])
if not contains -- $dst_host $hosts
set -a hosts $dst_host
end
end
set -l n_src_remote 0
for f in $src_remote_flags
if test $f -eq 1
set n_src_remote (math $n_src_remote + 1)
end
end
set -l any_remote 0
if test $dst_remote -eq 1; or test $n_src_remote -gt 0
set any_remote 1
end
# Failsafe: when a remote side is involved, verify ssh actually knows the
# host (e.g. via ~/.ssh/config) before copying anything. The probe is
# non-interactive; the real transfer below still uses your normal ssh
# config/auth (password prompt included).
if test $any_remote -eq 1
if not command -q ssh
echo "rscp: 'ssh' is not installed, but a remote copy was requested." >&2
return 1
end
if test (count $hosts) -gt 1
echo "rscp: copies between different remote hosts are not supported: $hosts" >&2
return 1
end
for h in $hosts
set -l probe_err (ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null $h true 2>&1)
set -l probe_st $status
if test $probe_st -ne 0
if string match -qi -- "*could not resolve*" $probe_err; or string match -qi -- "*name or service not known*" $probe_err; or string match -qi -- "*no address associated*" $probe_err; or string match -qi -- "*nodename nor servname*" $probe_err
echo "rscp: ssh host '$h' is unknown (check the 'Host $h' entry in ~/.ssh/config)." >&2
return 1
else if string match -qi -- "*permission denied*" $probe_err; or string match -qi -- "*authentication fail*" $probe_err
echo "rscp: note: key auth for '$h' failed; continuing, ssh may ask for a password." >&2
else
echo "rscp: cannot reach ssh host '$h': $probe_err" >&2
return 1
end
end
end
end
# Failsafe: if the destination already exists *and has content*, ask
# before overwriting. An existing but empty directory is not worth
# asking about - there is nothing that could be lost.
set -l dst_disp $dst_raw
if test "$dst" != "$dst_raw"
set dst_disp "$dst_raw ($dst)"
end
set -l dst_exists 0
set -l dst_is_dir 0
set -l dst_nonempty 0
if test $dst_remote -eq 1
set -l qdst (__rscp_shquote $dst_naslocal)
if ssh $dst_host test -e $qdst
set dst_exists 1
else if ssh $dst_host test -L $qdst
set dst_exists 1
end
if test $dst_exists -eq 1
if ssh $dst_host test -d $qdst
set dst_is_dir 1
set -l listing (ssh $dst_host ls -A $qdst 2>/dev/null)
set -l ls_st $status
if test $ls_st -ne 0; or test (count $listing) -gt 0
# Unlistable -> stay safe and treat it as non-empty.
set dst_nonempty 1
end
else
# File (or symlink): overwriting would replace content.
set dst_nonempty 1
end
end
else
if test -e "$dst"; or test -L "$dst"
set dst_exists 1
end
if test $dst_exists -eq 1
if test -d "$dst"
set dst_is_dir 1
set -l listing (command ls -A -- "$dst" 2>/dev/null)
set -l ls_st $status
if test $ls_st -ne 0; or test (count $listing) -gt 0
set dst_nonempty 1
end
else
set dst_nonempty 1
end
end
end
if test $dst_nonempty -eq 1
if test (count $srcs) -gt 1; and test $dst_is_dir -eq 0
echo "rscp: destination '$dst_disp' exists and is not a directory, but multiple sources were given." >&2
return 1
end
if test $force -eq 0
if not isatty stdin
echo "rscp: destination '$dst_disp' already exists and is not empty. Re-run interactively or pass -y/--yes to overwrite." >&2
return 1
end
if not read -l -P "rscp: destination '$dst_disp' already exists and is not empty. Overwrite/merge? [y/N] " confirm_raw
echo "rscp: aborted." >&2
return 1
end
switch (string lower -- (string trim -- "$confirm_raw"))
case y yes
# proceed
case '*'
echo "rscp: aborted."
return 1
end
end
end
# --no-perms: required - TrueNAS ZFS datasets use SMB ACLs and reject unix perms preservation
set -l base_opts -avh --no-perms --info=progress2 --partial
# Flags of the "to remote" direction; remote-to-remote via ssh on the NAS
# keeps these same flags (sudo for the chown, which needs root).
set -l to_remote_opts --rsync-path="sudo -n rsync" --chown=1000:0
if test $any_remote -eq 0
# PC -> PC goes through rsync with the same flags as rcp (no NAS-only
# --no-perms/--chown permission workarounds needed locally).
set -l local_opts -avh --progress
echo rsync $local_opts -- $srcs $dst
command rsync $local_opts -- $srcs $dst
return $status
end
if test $n_src_remote -eq (count $srcs); and test $dst_remote -eq 1
# NAS -> NAS: run rsync directly on the NAS itself. Only one remote
# host is possible here (checked above), so $hosts[1] is that host.
set -l rsrcs
for nl in $src_naslocals
set -a rsrcs (__rscp_shquote $nl)
end
set -l rdst (__rscp_shquote $dst_naslocal)
set -l ssh_tty
if isatty stdin
set ssh_tty -t
end
echo ssh $ssh_tty $hosts[1] sudo -n rsync $base_opts --chown=1000:0 -- $rsrcs $rdst
command ssh $ssh_tty $hosts[1] sudo -n rsync $base_opts --chown=1000:0 -- $rsrcs $rdst
return $status
end
if test $n_src_remote -gt 0; and test $n_src_remote -lt (count $srcs)
# Mixed local and remote sources cannot go into a single rsync call,
# so copy source by source. The overwrite question above was already
# asked once, hence -y here (each call still re-checks everything else).
for k in (seq (count $srcs))
rscp -y -- $srcs_raw[$k] $dst_raw
set -l st $status
if test $st -ne 0
return $st
end
end
return 0
end
# Single-sided copy: local -> NAS, NAS -> local, or one source of any kind.
set -l call_opts $base_opts
if test $dst_remote -eq 1
set -a call_opts $to_remote_opts
else if test $n_src_remote -gt 0
set -a call_opts --rsync-path="sudo -n rsync"
end
echo rsync $call_opts -- $srcs $dst
command rsync $call_opts -- $srcs $dst
return $status
end
function __rscp_shquote --description "Single-quote strings for a POSIX remote shell"
# Usage: __rscp_shquote STRING... ; prints each string single-quoted.
for s in $argv
set -l e (string replace -a -- "'" "'\"'\"'" $s)
echo "'$e'"
end
end
+16
View File
@@ -0,0 +1,16 @@
function sshkey --description "generate a SSH key"
if test (count $argv) -ne 1
echo "Usage: sshkey <file>"
echo "example: sshkey ~/.ssh/your_key_name"
return 1
end
set file $argv[1]
if test -e "$file"
echo "Error: $file already exists."
return 1
end
ssh-keygen -t ed25519 -f "$file" -C "$(hostname)" -N ""
end
+319
View File
@@ -0,0 +1,319 @@
function vrot -d 'Rotate a video with ffmpeg: metadata-only by default, re-encode with -r'
argparse -n vrot 'h/help' 'r/reencode' 'a/angle=' 'p/preset=' -- $argv
or return 2
if set -q _flag_help
__vrot_usage
return 0
end
if test (count $argv) -lt 1
__vrot_usage
return 2
end
set -q _flag_angle; or set _flag_angle 90
set -q _flag_preset; or set _flag_preset medium
switch $_flag_angle
case 90 180 270
case '*'
__vrot_error "angle must be 90, 180 or 270 (got '$_flag_angle')"
return 2
end
__vrot_colors
set -l want_reencode 0
set -q _flag_reencode; and set want_reencode 1
set -l rc 0
for file in $argv
if not test -f "$file"
__vrot_error "no such file: '$file'"
set rc 1
continue
end
__vrot_one "$file" "$_flag_angle" "$_flag_preset" "$want_reencode"
or set rc 1
end
return $rc
end
function __vrot_one
set -l file $argv[1]
set -l angle $argv[2]
set -l preset $argv[3]
set -l want_reencode $argv[4]
set -l name (path basename "$file")
set -l ext (path extension "$file")
set -l out (path change-extension '' "$file")_rot$ext
set -l outname (path basename "$out")
__vrot_banner "$name$outname"
set -l lines (ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,r_frame_rate,nb_frames:format=duration,bit_rate \
-of default=noprint_wrappers=1 "$file")
set -l codec (string match 'codec_name=*' -- $lines | string replace 'codec_name=' '')[1]
set -l width (string match 'width=*' -- $lines | string replace 'width=' '')[1]
set -l height (string match 'height=*' -- $lines | string replace 'height=' '')[1]
set -l fpsraw (string match 'r_frame_rate=*' -- $lines | string replace 'r_frame_rate=' '')[1]
set -l frames (string match 'nb_frames=*' -- $lines | string replace 'nb_frames=' '')[1]
set -l duration (string match 'duration=*' -- $lines | string replace 'duration=' '')[1]
set -l bitrate (string match 'bit_rate=*' -- $lines | string replace 'bit_rate=' '')[1]
set -l info "$width"x"$height"
if test -n "$codec"
set info "$info "(string upper "$codec")
end
if test -n "$fpsraw"; and string match -rq '^[0-9]+/[0-9]+$' "$fpsraw"; and not string match -q '*/0' "$fpsraw"
set info "$info "(math -s 2 "$fpsraw")" fps"
end
if test -n "$duration"; and string match -rq '^[0-9.]+$' "$duration"
set info "$info "(__vrot_fmtsecs "$duration")
end
if test -n "$bitrate"; and string match -rq '^[0-9.]+$' "$bitrate"
set info "$info "(math -s 1 "$bitrate/1000000")" Mbit/s"
end
echo "$vrot_c_dim $info$vrot_c_reset"
if test "$file" = "$out"
__vrot_error "output would overwrite input: '$out'"
return 1
end
if test -e "$out"
read -l -P "vrot: '$out' exists. Overwrite? [y/N] " ans
if not string match -qi 'y' "$ans"
echo "$vrot_c_dim skipped: $out$vrot_c_reset"
return 1
end
rm -f "$out"
end
if test "$want_reencode" -eq 1
__vrot_reencode "$file" "$out" "$angle" "$preset" "$height" "$codec" "$duration" "$frames"
return $status
end
echo "$vrot_c_dim mode: metadata-only rotation (lossless, instant)$vrot_c_reset"
ffmpeg -hide_banner -loglevel error -nostdin -i "$file" -map 0 -c copy -ignore_unknown \
-movflags +faststart -metadata:s:v:0 rotate=$angle "$out"
if test $status -eq 0
__vrot_summary "$out"
return 0
end
echo "$vrot_c_warn ↷ dropping unsupported data/attachment tracks, retrying…$vrot_c_reset"
rm -f "$out"
ffmpeg -hide_banner -loglevel error -nostdin -i "$file" -map 0 -map '-0:d' -map '-0:t' \
-c copy -movflags +faststart -metadata:s:v:0 rotate=$angle "$out"
if test $status -eq 0
__vrot_summary "$out"
return 0
end
echo "$vrot_c_warn ↷ metadata rotation unsupported here, re-encoding instead…$vrot_c_reset"
rm -f "$out"
__vrot_reencode "$file" "$out" "$angle" "$preset" "$height" "$codec" "$duration" "$frames"
end
function __vrot_reencode
set -l file $argv[1]
set -l out $argv[2]
set -l angle $argv[3]
set -l preset $argv[4]
set -l height $argv[5]
set -l codec $argv[6]
set -l duration $argv[7]
set -l frames $argv[8]
test -n "$height"; or set height 1080
set -l enc libx264
switch "$codec"
case 'hevc*' 'h265*' 'h266*'
set enc libx265
end
set -l crf 20
set -l maxrate 20M
set -l bufsize 40M
if test $height -ge 2160
set crf 22; set maxrate 40M; set bufsize 80M
else if test $height -ge 1440
set crf 21; set maxrate 30M; set bufsize 60M
else if test $height -ge 1080
set crf 20; set maxrate 20M; set bufsize 40M
else if test $height -ge 720
set crf 19; set maxrate 10M; set bufsize 20M
else
set crf 18; set maxrate 6M; set bufsize 12M
end
set -l vf 'transpose=1'
switch $angle
case 180
set vf 'transpose=1,transpose=1'
case 270
set vf 'transpose=2'
end
set -l faststart
switch (string lower (path extension "$out"))
case '.mp4' '.mov' '.m4v'
set faststart '-movflags' '+faststart'
end
echo "$vrot_c_dim mode: re-encode ($enc · crf $crf · cap $maxrate)$vrot_c_reset"
set -l total_frames ''
string match -rq '^\d+$' "$frames"; and test "$frames" -gt 0; and set total_frames $frames
set -l out_t ''
set -l frame 0
set -l fps_txt ''
set -l bitrate_txt ''
set -l speed_txt ''
ffmpeg -hide_banner -loglevel error -nostdin -progress pipe:1 -i "$file" \
-map 0:v -map '0:a?' -map '0:s?' -ignore_unknown -vf "$vf" -c:v $enc -crf $crf \
-maxrate $maxrate -bufsize $bufsize -preset $preset -c:a copy -c:s copy \
$faststart "$out" | while read -l line
switch "$line"
case 'frame=*'
set frame (string replace 'frame=' '' -- "$line")
case 'fps=*'
set fps_txt (string replace 'fps=' '' -- "$line")"fps"
case 'bitrate=*'
set bitrate_txt (string replace 'bitrate=' '' -- "$line")
if string match -q '*kbits/s' "$bitrate_txt"
set bitrate_txt (math -s 1 (string replace 'kbits/s' '' -- "$bitrate_txt") / 1000)"Mbit/s"
else if string match -q '*Mbits/s' "$bitrate_txt"
set bitrate_txt (string replace 'Mbits/s' 'Mbit/s' -- "$bitrate_txt")
end
case 'out_time=*'
set -l t (string replace 'out_time=' '' -- "$line")
set -l parts (string split ':' -- "$t")
if test (count $parts) -eq 3; and string match -rq '^\d+$' "$parts[1]"; and string match -rq '^\d+$' "$parts[2]"; and string match -rq '^[\d.]+$' "$parts[3]"
set out_t (math "$parts[1]*3600+$parts[2]*60+$parts[3]")
end
case 'speed=*'
set speed_txt (string replace 'speed=' '' -- "$line")
end
if isatty stdout
printf '\r\033[K'
set -l pct '--.-%'
set -l eta_txt ''
set -l bar (string repeat -n 24 '░')
set -l frac ''
if test -n "$total_frames"; and string match -rq '^\d+$' "$frame"; and test "$total_frames" -gt 0
set frac (math "min(1, $frame/$total_frames)")
else if test -n "$out_t"; and string match -rq '^[0-9.]+$' "$duration"; and not string match -rq '^0+(\.0*)?$' "$duration"
set frac (math "min(1, $out_t/$duration)")
end
if test -n "$frac"
set -l filled (math "floor($frac*24)")
set -l bar (string repeat -n $filled '█')
set bar "$bar"(string repeat -n (math "24-$filled") '░')
set pct (math -s 1 "$frac*100")%
set -l sp (string replace -r '[xX]$' '' -- "$speed_txt")
if test -n "$sp"; and string match -rq '^[0-9.]+$' "$sp"; and not string match -rq '^0+(\.0*)?$' "$sp"; and test -n "$out_t"; and string match -rq '^[0-9.]+$'
"$duration"
set eta_txt " ETA "(__vrot_fmtsecs (math "($duration - $out_t)/$sp"))
end
end
set -l frame_txt $frame
if test -n "$total_frames"
set frame_txt "$frame/$total_frames"
end
echo -n " $vrot_c_ok$bar$vrot_c_reset $pct frame=$frame_txt $fps_txt $bitrate_txt $speed_txt$eta_txt"
end
end
set -l ff_status $pipestatus[1]
printf '\n'
if test $ff_status -ne 0
__vrot_error "encoding failed (ffmpeg exited $ff_status)"
return 1
end
__vrot_summary "$out"
end
function __vrot_summary
set -l out $argv[1]
set -l size ''
if command -q numfmt
set size (numfmt --to=iec --suffix=B -- (stat -c %s -- "$out") 2>/dev/null)
else
set size (du -h -- "$out" | string replace -r '\t.*' '')
end
set -l dims (ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height -of default=noprint_wrappers=1:nokey=1 "$out" \
| string match -r '^\d+$' | string join '×')
set -l extra ''
if test -n "$dims"
set extra " · $dims"
end
echo "$vrot_c_ok$out$vrot_c_dim ($size$extra)$vrot_c_reset"
end
function __vrot_banner
set -l title $argv[1]
echo "$vrot_c_dim"(string repeat -n 58 '─')"$vrot_c_reset"
echo "$vrot_c_hi $title$vrot_c_reset"
end
function __vrot_colors
set -q vrot_colors_set; and return 0
set -g vrot_colors_set 1
if isatty stdout
set -g vrot_c_hi (set_color brwhite --bold)
set -g vrot_c_dim (set_color brblack)
set -g vrot_c_ok (set_color brgreen)
set -g vrot_c_warn (set_color bryellow)
set -g vrot_c_err (set_color brred)
set -g vrot_c_reset (set_color normal)
else
for c in hi dim ok warn err reset
set -g vrot_c_$c ''
end
end
end
function __vrot_fmtsecs
set -l s (math "max(0, round($argv[1]))")
set -l h (math "floor($s/3600)")
set -l m (math "floor($s%3600/60)")
set -l sec (math "$s%60")
if test $h -gt 0
printf '%02d:%02d:%02d' $h $m $sec
else
printf '%02d:%02d' $m $sec
end
end
function __vrot_error
echo "$vrot_c_err""vrot: "$argv"$vrot_c_reset" >&2
end
function __vrot_usage
echo 'usage: vrot [options] <video> [<video> ...]'
echo
echo 'Rotates one or more videos and writes <name>_rot.<ext> next to each.'
echo
echo 'Default mode is metadata-only rotation: lossless and instant. Works for'
echo 'MP4/MOV/M4V (including GoPro files; unsupported data/timecode tracks are'
echo 'dropped automatically). If the container cannot carry the flag, vrot'
echo 'falls back to re-encoding, with a live progress bar. Players that'
echo 'ignore rotation flags need -r.'
echo
echo 'options:'
echo ' -a, --angle <90|180|270> clockwise angle (default 90)'
echo ' -r, --reencode rotate pixels by re-encoding'
echo ' -p, --preset <name> x264/x265 preset (default medium)'
echo ' -h, --help show this help'
end
+44 -17
View File
@@ -20,31 +20,58 @@ mount_cifs() {
echo "Successfully mounted: $mount_point" echo "Successfully mounted: $mount_point"
} }
function is_mounted() {
mountpoint -q "$1"
}
# Mount FRITZ.NAS (from fstab line 1) # Mount FRITZ.NAS (from fstab line 1)
if ping -c 1 -W 1 "$HOST" >/dev/null 2>&1; then if ! is_mounted "/home/honney/mount/fritzNAS"; then
if ping -c 1 -W 1 "192.168.1.1" >/dev/null 2>&1; then
mount_cifs "//192.168.1.1/FRITZ.NAS" \ mount_cifs "//192.168.1.1/FRITZ.NAS" \
"/home/honney/mount/fritzNAS" \ "/home/honney/mount/fritzNAS" \
"credentials=/home/honney/.cred/samba_credentials,uid=1000,gid=1000,vers=3.0,cache=none,nounix,noserverino,file_mode=0755,dir_mode=0755" "credentials=/home/honney/.cred/samba_credentials,uid=1000,gid=1000,vers=3.0,cache=none,nounix,noserverino,file_mode=0755,dir_mode=0755"
fi fi
fi
if ping -c 1 -W 1 "100.64.0.3" >/dev/null 2>&1; then echo ""
# Mount Data (from fstab line 2) mount_points=("/home/honney/mount/Data" "/home/honney/mount/Media" "/home/honney/mount/Ripping" "/home/honney/mount/Apps")
mount_cifs "//100.64.0.3/Data" \
"/home/honney/mount/Data" \
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
# Mount Media (from fstab line 3)
mount_cifs "//100.64.0.3/Media" \
"/home/honney/mount/Media" \
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
# Mount Ripping (from fstab line 4) if ping -c 1 -W 1 "192.168.188.122" >/dev/null 2>&1; then
mount_cifs "//100.64.0.3/Ripping" \ echo "192.168.188.122, mounting shares..."
"/home/honney/mount/Ripping" \ echo ""
mounts=("//192.168.188.122/Data" "//192.168.188.122/Media" "//192.168.188.122/Ripping" "//192.168.188.122/Apps")
for i in "${!mounts[@]}"; do
mount="${mounts[$i]}"
mount_point="${mount_points[$i]}"
echo "Checking $mount_point"
if ! is_mounted "$mount_point"; then
echo "$mount_point unmounted"
mount_cifs "$mount" \
"$mount_point" \
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose" "credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
else
echo "$mount_point already mounted"
fi
echo ""
done
# Mount Apps (from fstab line 5) elif ping -c 1 -W 1 "100.64.0.3" >/dev/null 2>&1; then
mount_cifs "//100.64.0.3/Apps" \ echo "192.168.188.122 unreachable"
"/home/honney/mount/Apps" \ echo "100.64.0.3 reachable, mounting shares..."
echo ""
mounts=("//100.64.0.3/Data" "//100.64.0.3/Media" "//100.64.0.3/Ripping" "//100.64.0.3/Apps")
for i in "${!mounts[@]}"; do
mount="${mounts[$i]}"
mount_point="${mount_points[$i]}"
echo "Checking $mount_point"
if ! is_mounted "$mount_point"; then
echo "$mount_point unmounted"
mount_cifs "$mount" \
"$mount_point" \
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose" "credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
else
echo "$mount_point already mounted"
fi
echo ""
done
fi fi
+49 -25
View File
@@ -1,35 +1,59 @@
#!/bin/bash #!/bin/bash
# Source the functions file function is_mounted() {
source "$HOME/.config/function_helper.sh" mountpoint -q "$1"
}
# Define mount points function unmount() {
MOUNT_POINT_RAID="$HOME/Raid/" if is_mounted "$1"; then
MOUNT_POINT_SSD="$HOME/Server-SSD/" if ! sudo umount -l "$1"; then
echo "Unmount failed: $1"
PASSWORD_FILE="$HOME/.cred/credentials.txt" return 1
PASSWORD=$(<"$PASSWORD_FILE")
# Unmount RAID
if is_mounted "$MOUNT_POINT_RAID"; then
if echo "$PASSWORD" | sudo -S umount "$MOUNT_POINT_RAID"; then
send_notification "low" "Unmount Successful" "Unmounted $MOUNT_POINT_RAID successfully." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-encrypted-symbolic.svg"
else else
send_notification "high" "Unmount Failed" "Failed to unmount $MOUNT_POINT_RAID." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-symbolic.svg" echo "Unmount completed: $1"
exit 1
fi fi
else else
send_notification "low" "Not Mounted" "$MOUNT_POINT_RAID is not mounted." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk.svg" echo "$1 is not mounted"
fi
}
function force_unmount() {
if is_mounted "$1"; then
if ! sudo umount -fl "$1"; then
echo "Unmount failed: $1"
return 1
else
echo "Unmount completed: $1"
fi
else
echo "$1 is not mounted"
fi
}
function has_connection() {
if ping -c 1 -W 1 "$1" &>/dev/null; then
return 0
else
return 1
fi
}
mounts=("/home/honney/mount/Data" "/home/honney/mount/Media" "/home/honney/mount/Ripping" "/home/honney/mount/Apps")
if has_connection "100.64.0.3" || has_connection "192.168.188.122"; then
for mount in "${mounts[@]}"; do
unmount "$mount"
done
else
for mount in "${mounts[@]}"; do
force_unmount "$mount"
done
fi fi
# Unmount SSD if has_connection "192.168.1.1"; then
if is_mounted "$MOUNT_POINT_SSD"; then unmount "/home/honney/mount/fritzNAS"
if echo "$PASSWORD" | sudo -S umount "$MOUNT_POINT_SSD"; then
send_notification "low" "Unmount Successful" "Unmounted $MOUNT_POINT_SSD successfully." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-encrypted-symbolic.svg"
else else
send_notification "high" "Unmount Failed" "Failed to unmount $MOUNT_POINT_SSD." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-symbolic.svg" force_unmount "/home/honney/mount/fritzNAS"
exit 1
fi
else
send_notification "low" "Not Mounted" "$MOUNT_POINT_SSD is not mounted." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk.svg"
fi fi
exit 0