feat(user/triml.sh):Defronts shared filename prefixes
authorSteven Baltakatei Sandoval <baltakatei@gmail.com>
Wed, 11 Sep 2024 04:30:33 +0000 (04:30 +0000)
committerSteven Baltakatei Sandoval <baltakatei@gmail.com>
Wed, 11 Sep 2024 04:30:33 +0000 (04:30 +0000)
user/triml.sh [new file with mode: 0755]

diff --git a/user/triml.sh b/user/triml.sh
new file mode 100755 (executable)
index 0000000..45dbe4a
--- /dev/null
@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+# Desc: Rename files to remove common prefix
+# Usage: triml.sh [FILE] ([FILE]…)
+# Example: triml.sh ./*.txt
+# Version: 0.0.1
+
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+get_prefix() {
+    # Desc: Iteratively identify common prefix
+    # Input: "$@"  arguments
+    # Output: stdout
+    local prefix="$1"; # start with first arg
+    shift; # don't compare first to first
+    for arg in "$@"; do
+        while [[ "$arg" != "$prefix"* ]]; do
+            prefix="${prefix%?}"; # trim end of prefix if match
+        done;
+    done;
+    printf "%s" "$prefix";
+}; # Get common prefix of arguments
+show_usage() {
+    # Desc: Display script usage information
+    # Usage: show_usage
+    # Version 0.0.2
+    # Input: none
+    # Output: stdout
+    # Depends: GNU-coreutils 8.30 (cat)
+    cat <<'EOF'
+    USAGE:
+        triml.sh FILE [FILE…]
+
+    OPTIONS:
+        (none)
+
+    EXAMPLE:
+      triml.sh
+      triml.sh ./*.txt
+EOF
+} # Display information on how to use this script.
+prompt_continue() {
+    # Desc: Prompt user to go approve/disapprove or list files to be moved.
+    while true; do
+        read -rp "Rename ${#args[@]} files? (y/N or l/list): " choice;
+        case "${choice,,}" in
+            y|yes)
+                yell "STATUS:Renaming...";
+                return 0;
+                ;;
+            l|list)
+                for i in "${!args[@]}"; do
+                    yell "Rename: ${args[i]} -> ${args_defront[i]}";
+                done;
+                ;;
+            n|no)
+                die "FATAL:Operation aborted.";
+                ;;
+            *)
+                yell "Invalid option.";
+        esac;
+    done;
+}; # prompt user to continue operation
+main () {
+    declare -a args args_defront;
+    declare prefix;
+    declare path_dir name_file name_file_new;
+    
+    # Check if no arguments are passed
+    if [[ "$#" -le 0 ]]; then
+        ## Act on working dir files
+        mapfile -t args < <(find . -mindepth 1 -maxdepth 1 -type f);
+    else
+        ## Act on argument-specified file paths
+        args=("$@");
+    fi;
+
+    # Check that all args are file paths
+    for arg in "${args[@]}"; do
+        if [[ ! -f "$arg" ]]; then
+            show_usage;
+            die "FATAL:Not a file:${arg}"; fi;
+    done;
+    
+    # Get common prefix of all file basenames
+    ## Assemble directory paths and file name arrays
+    for i in "${!args[@]}"; do
+        #args_path[i]="$(dirname "${args[i]}")";
+        args_file[i]="$(basename "${args[i]}")";
+    done;
+    prefix="$(get_prefix "${args_file[@]}")";
+    #declare -p args prefix; # debug
+    if [[ "${#prefix}" -le 0 ]]; then
+       #declare -p prefix; # debug
+       die "FATAL:No file prefix found."; fi;
+
+    # Assemble paths with defronted basenames
+    for i in "${!args[@]}"; do
+        path_dir="$(dirname "${args[i]}")";
+        name_file="$(basename "${args[i]}")";
+        name_file_new="${name_file#"${prefix}"}";
+        args_defront[i]="${path_dir}/${name_file_new}";
+    done;
+    
+    # Throw rename warning
+    must prompt_continue;
+    
+    # Rename files to defront prefix
+    for i in "${!args[@]}"; do
+        if mv -n "${args[i]}" "${args_defront[i]}"; then
+            yell "STATUS:Moved ${args[i]} to ${args_defront[i]}";
+        else
+            die "FATAL:Failed to move ${args[i]} to ${args_defront[i]}";
+        fi;
+    done;
+};
+main "$@";
+
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+