From 75baf70102a9c94e694c9ac39deae404176b815b Mon Sep 17 00:00:00 2001 From: Steven Baltakatei Sandoval Date: Mon, 10 Jun 2024 19:41:35 +0000 Subject: [PATCH 1/1] feat(user/bkmpv2): v0.1.0: Permit specifying files as well as dirs --- user/bkmpv2 | 183 +++++++++++++++++++++++++--------------------------- 1 file changed, 88 insertions(+), 95 deletions(-) diff --git a/user/bkmpv2 b/user/bkmpv2 index 19f605e..d44fff7 100755 --- a/user/bkmpv2 +++ b/user/bkmpv2 @@ -1,11 +1,12 @@ #!/usr/bin/env bash -# Desc: Wrapper for mpv that accepts directory paths via posargs or stdin lines +# Desc: Wrapper for mpv that accepts directory or file paths via posargs or stdin lines # Usage: bkmpv2 [DIR] -# Version: 0.0.1 +# Version: 0.1.0 # Depends: GNU Parallel, GNU Bash v5.1.16, mpv v0.34.1, bc v1.07.1 # Ref/Attrib: [1] Tange, Ole. GNU Parallel with Bash Array. 2019-03-24. https://unix.stackexchange.com/a/508365/411854 # Example: find $HOME/Music -type d | bkmpv2 # Example: bkmpv2 $HOME/Music/ +# Example: find $HOME -type f -name "*.mp3" | bkmpv2 # Note: Does not follow symlinks # Find settings @@ -29,23 +30,23 @@ checkapp() { # Input: global assoc. array 'appRollCall' # Output: adds/updates key(value) to global assoc array 'appRollCall' # Depends: bash 5.0.3 - local returnState + local returnState #===Process Args=== for arg in "$@"; do - if command -v "$arg" 1>/dev/null 2>&1; then # Check if arg is a valid command - appRollCall[$arg]="true"; - if ! [ "$returnState" = "false" ]; then returnState="true"; fi; - else - appRollCall[$arg]="false"; returnState="false"; - fi; + if command -v "$arg" 1>/dev/null 2>&1; then # Check if arg is a valid command + appRollCall[$arg]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi; + else + appRollCall[$arg]="false"; returnState="false"; + fi; done; #===Determine function return code=== if [ "$returnState" = "true" ]; then - return 0; + return 0; else - return 1; + return 1; fi; } # Check that app exists checkfile() { @@ -60,19 +61,19 @@ checkfile() { #===Process Args=== for arg in "$@"; do - if [ -f "$arg" ]; then - fileRollCall["$arg"]="true"; - if ! [ "$returnState" = "false" ]; then returnState="true"; fi; - else - fileRollCall["$arg"]="false"; returnState="false"; - fi; + if [ -f "$arg" ]; then + fileRollCall["$arg"]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi; + else + fileRollCall["$arg"]="false"; returnState="false"; + fi; done; - + #===Determine function return code=== if [ "$returnState" = "true" ]; then - return 0; + return 0; else - return 1; + return 1; fi; } # Check that file exists checkdir() { @@ -87,19 +88,19 @@ checkdir() { #===Process Args=== for arg in "$@"; do - if [ -d "$arg" ]; then - dirRollCall["$arg"]="true"; - if ! [ "$returnState" = "false" ]; then returnState="true"; fi - else - dirRollCall["$arg"]="false"; returnState="false"; - fi + if [ -d "$arg" ]; then + dirRollCall["$arg"]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi + else + dirRollCall["$arg"]="false"; returnState="false"; + fi done - + #===Determine function return code=== if [ "$returnState" = "true" ]; then - return 0; + return 0; else - return 1; + return 1; fi } # Check that dir exists displayMissing() { @@ -111,21 +112,21 @@ displayMissing() { # Depends: bash 5, checkAppFileDir() local missingApps value appMissing missingFiles fileMissing local missingDirs dirMissing - + #==BEGIN Display errors== #===BEGIN Display Missing Apps=== missingApps="Missing apps :"; #for key in "${!appRollCall[@]}"; do echo "DEBUG:$key => ${appRollCall[$key]}"; done for key in "${!appRollCall[@]}"; do - value="${appRollCall[$key]}"; - if [ "$value" = "false" ]; then - #echo "DEBUG:Missing apps: $key => $value"; - missingApps="$missingApps""$key "; - appMissing="true"; - fi; + value="${appRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing apps: $key => $value"; + missingApps="$missingApps""$key "; + appMissing="true"; + fi; done; if [ "$appMissing" = "true" ]; then # Only indicate if an app is missing. - echo "$missingApps" 1>&2; + echo "$missingApps" 1>&2; fi; unset value; #===END Display Missing Apps=== @@ -134,15 +135,15 @@ displayMissing() { missingFiles="Missing files:"; #for key in "${!fileRollCall[@]}"; do echo "DEBUG:$key => ${fileRollCall[$key]}"; done for key in "${!fileRollCall[@]}"; do - value="${fileRollCall[$key]}"; - if [ "$value" = "false" ]; then - #echo "DEBUG:Missing files: $key => $value"; - missingFiles="$missingFiles""$key "; - fileMissing="true"; - fi; + value="${fileRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing files: $key => $value"; + missingFiles="$missingFiles""$key "; + fileMissing="true"; + fi; done; if [ "$fileMissing" = "true" ]; then # Only indicate if an app is missing. - echo "$missingFiles" 1>&2; + echo "$missingFiles" 1>&2; fi; unset value; #===END Display Missing Files=== @@ -151,15 +152,15 @@ displayMissing() { missingDirs="Missing dirs:"; #for key in "${!dirRollCall[@]}"; do echo "DEBUG:$key => ${dirRollCall[$key]}"; done for key in "${!dirRollCall[@]}"; do - value="${dirRollCall[$key]}"; - if [ "$value" = "false" ]; then - #echo "DEBUG:Missing dirs: $key => $value"; - missingDirs="$missingDirs""$key "; - dirMissing="true"; - fi; + value="${dirRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing dirs: $key => $value"; + missingDirs="$missingDirs""$key "; + dirMissing="true"; + fi; done; if [ "$dirMissing" = "true" ]; then # Only indicate if an dir is missing. - echo "$missingDirs" 1>&2; + echo "$missingDirs" 1>&2; fi; unset value; #===END Display Missing Directories=== @@ -185,21 +186,21 @@ checkInt() { #===Process Arg=== if [[ $# -ne 1 ]]; then - die "ERROR:Invalid number of arguments:$#"; + die "ERROR:Invalid number of arguments:$#"; fi; - + RETEST1='^[0-9]+$'; # Regular Expression to test if [[ ! $1 =~ $RETEST1 ]] ; then - returnState="false"; + returnState="false"; else - returnState="true"; + returnState="true"; fi; #===Determine function return code=== if [ "$returnState" = "true" ]; then - return 0; + return 0; else - return 1; + return 1; fi; } # Checks if arg is integer read_stdin() { @@ -214,8 +215,8 @@ read_stdin() { # Store stdin if [[ -p /dev/stdin ]]; then input_stdin="$(cat -)"; - fi; - + fi; + # Store as output array elements ## Read in stdin if [[ -n $input_stdin ]]; then @@ -235,12 +236,12 @@ read_psarg() { # Depends: GNU bash (version 5.1.16) # Version: 0.0.1 local input_psarg output; - + # Store arguments if [[ $# -gt 0 ]]; then input_psarg="$*"; fi; - + # Store as output array elements ## Read in positional arguments if [[ -n $input_psarg ]]; then @@ -268,7 +269,7 @@ main() { # var: fc_redbase logarithm base to reduce output file count local re_dotfile; - declare -a dirs_stdin dirs_psarg; + declare -a files_stdin dirs_stdin dirs_psarg; declare -a paths_files; declare list_paths_files; declare -a cmd_args; @@ -280,45 +281,37 @@ main() { re_dotfile="^\."; # first char is a dot while read -r line; do line="$(readlink -e "$line")"; - # Check if dir - if [[ ! -d "$line" ]]; then - echo "ERROR:Not a dir:$line" 1>&2; + line_bn="$(basename "$line")"; + # Check if dir and not dotfile + if [[ -d "$line" ]] && [[ ! "$line_bn" =~ $re_dotfile ]]; then + dirs_stdin+=("$line"); continue; fi; - dir_name="$(basename "$line")"; - # Exclude dotdirs - if [[ "$dir_name" =~ $re_dotfile ]]; then - echo "ERROR:Is a dotdir:$line" 1>&2; - continue - fi; - dirs_stdin+=("$line"); - done < <(read_stdin); - yell "STATUS:$SECONDS:Read stdin."; - ## Read positional arguments as lines - re_dotfile="^\."; # first char is a dot - while read -r line; do - line="$(readlink -e "$line")"; - # Check if dir - if [[ ! -d "$line" ]]; then - echo "ERROR:Not a dir:$line" 1>&2; + + # Check if file + if [[ -f "$line" ]]; then + files_stdin+=("$line"); continue; fi; - dir_name="$(basename "$line")"; - # Exclude dotdirs - if [[ "$dir_name" =~ $re_dotfile ]]; then - echo "ERROR:Is a dotdir:$line" 1>&2; - continue - fi; - dirs_psarg+=("$line"); - done < <(read_psarg "$@"); - yell "STATUS:$SECONDS:Read posargs."; - + + # Throw warning + yell "WARNING:Not a valid dir or file:$line"; + done < <( read_stdin; read_psarg "$@"; ); + yell "STATUS:$SECONDS:Read stdin and psargs."; + # Catch all arrays empty - if [[ "${#dirs_stdin[@]}" -le 0 ]] && [[ "${#dirs_psarg[@]}" -le 0 ]]; then - die "FATAL:No valid directories provided."; + if [[ "${#dirs_stdin[@]}" -le 0 ]] && \ + [[ "${#dirs_psarg[@]}" -le 0 ]] && \ + [[ "${#files_stdin[@]}" -le 0 ]]; then + die "FATAL:No valid directories or files provided."; fi; # Generate file list + ## Add stdin argument input + if [[ "${#files_stdin[@]}" -gt 0 ]]; then + paths_files+=("${files_stdin[@]}"); + fi; + ## Call find_filelist() in parallel for positional argument input if [[ "${#dirs_psarg[@]}" -gt 0 ]]; then fdepth="$fdepth_posarg"; export fdepth; # for dirs from positional arguments @@ -354,7 +347,7 @@ main() { bc_exp="$fc_falloff * (1 + l( $fc / $fc_falloff )/l($fc_redbase))"; fc_out="$( echo "$bc_exp" | bc -l )"; else - fc_out="$fc"; + fc_out="$fc"; fi; ## Reduce output file count by fixed fraction (bkshuf optimization) fc_out="$(echo "$fc_out * 0.75" | bc -l)"; @@ -365,7 +358,7 @@ main() { ### Round file count down fc_out="$(printf "%.0f" "$fc_out")"; # round float down to int ### Get neighbor-preserving shuffled subset (size $fc_out) - yell "STATUS:$SECONDS:Selecting $fc_out files via bkshuf..."; + yell "STATUS:$SECONDS:Selecting $fc_out of $fc files via bkshuf..."; must \ echo -n "$list_paths_files" | \ bkshuf "$fc_out" > "$list_paths_files_tmp"; -- 2.30.2