diff --git a/commands/echo-affirmative b/commands.beta/echo-affirmative
similarity index 97%
rename from commands/echo-affirmative
rename to commands.beta/echo-affirmative
index 6dae84c47..bd31946bc 100755
--- a/commands/echo-affirmative
+++ b/commands.beta/echo-affirmative
@@ -13,7 +13,6 @@ function echo_affirmative() (
cat <<-EOF >/dev/stderr
ABOUT:
For each , output 'yes' if affirmative, 'no' if non-affirmative, otherwise note the invalidity to stderr.
- Using [is-affirmative] for the validation.
USAGE:
echo-affirmative [...options] [--] ...
diff --git a/commands.beta/echo-exit-affirmative b/commands.beta/echo-exit-affirmative
index bfcb4ab52..b8c736f58 100755
--- a/commands.beta/echo-exit-affirmative
+++ b/commands.beta/echo-exit-affirmative
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+# @should be renamed to eval-then-affirm-status
+
function echo_exit_affirmative() (
source "$DOROTHY/sources/bash.bash"
diff --git a/commands.beta/echo-exit-status b/commands.beta/echo-exit-status
index c4e82bc01..954e05a22 100755
--- a/commands.beta/echo-exit-status
+++ b/commands.beta/echo-exit-status
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+# @should be renamed to eval-then-echo-status
+
function echo_exit_status() (
source "$DOROTHY/sources/bash.bash"
diff --git a/commands.beta/echo-if-directory b/commands.beta/echo-if-directory
index c1b1ca714..663976b97 100755
--- a/commands.beta/echo-if-directory
+++ b/commands.beta/echo-if-directory
@@ -6,7 +6,7 @@ function echo_if_directory() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Output inputs that are directories.
+ Output inputs that are directories (or symlinks to directories).
USAGE:
echo-if-directory [...options] [---] ...
diff --git a/commands/echo-non-affirmative b/commands.beta/echo-non-affirmative
similarity index 100%
rename from commands/echo-non-affirmative
rename to commands.beta/echo-non-affirmative
diff --git a/commands.beta/echo-with-empty-fallback b/commands.beta/echo-with-empty-fallback
new file mode 100755
index 000000000..4a76f01ac
--- /dev/null
+++ b/commands.beta/echo-with-empty-fallback
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+function echo_with_empty_fallback() (
+ source "$DOROTHY/sources/stdinargs.bash"
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Output if all is zero-length.
+ Similar to [echo-with-whitespace-fallback], [eval-on-empty-stdin], [eval-on-not-empty-stdin].
+
+ USAGE:
+ echo-with-empty-fallback [...options] [--] ...
+ echo-lines ... | echo-with-empty-fallback [...options]
+
+ OPTIONS:
+ | --fallback=
+ The fallback to use if is empty.
+
+ $(stdinargs_options_help --)
+
+ EXAMPLE:
+
+ echo-with-empty-fallback 'my-fallback-value'
+
+ my-fallback-value
+ # exit status: 0
+
+ printf '' | echo-with-empty-fallback 'my-fallback-value'
+
+ my-fallback-value
+ # exit status: 0
+
+ printf ' ' | echo-with-empty-fallback 'my-fallback-value' --stdin
+
+ # exit status: 0
+
+ printf 'value' | echo-with-empty-fallback 'my-fallback-value' --stdin
+
+ value
+ # exit status: 0
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process our own arguments, delegate everything else to stdinargs
+ local rand="$RANDOM"
+ local item option_fallback="$rand" option_args=()
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--fallback='*) option_fallback="${item#*=}" ;;
+ # forward to stdinargs, however support mixing and matching of our options, with stdinarg options
+ '--')
+ option_args+=("$item" "$@")
+ shift $#
+ break
+ ;;
+ '--'*) option_args+=("$item") ;;
+ *)
+ if [[ $option_fallback == "$rand" ]]; then
+ option_fallback="$item"
+ else
+ option_args+=("$item")
+ fi
+ ;;
+ esac
+ done
+
+ # check for expected
+ if [[ $option_fallback == "$rand" ]]; then
+ help 'Missing required argument: '
+ fi
+
+ # action
+ local inputs=''
+ function on_inline {
+ inputs+="$1"
+ }
+ function on_line {
+ inputs+="$1"$'\n'
+ return 210 # ECUSTOM 210 Processing complete, exit early
+ }
+ function on_finish {
+ if [[ -z $inputs ]]; then
+ __print_string "$fallback"
+ else
+ __print_string "$inputs"
+ fi
+ }
+ stdinargs "${option_args[@]}"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ echo_with_empty_fallback "$@"
+fi
diff --git a/commands.beta/echo-if-empty b/commands.beta/echo-with-whitespace-fallback
similarity index 69%
rename from commands.beta/echo-if-empty
rename to commands.beta/echo-with-whitespace-fallback
index d754dc314..46cc4caa2 100755
--- a/commands.beta/echo-if-empty
+++ b/commands.beta/echo-with-whitespace-fallback
@@ -1,16 +1,17 @@
#!/usr/bin/env bash
-function echo_if_empty() (
+function echo_with_whitespace_fallback() (
source "$DOROTHY/sources/stdinargs.bash"
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Output if is empty.
+ Output if all is only whitespace.
+ Similar to [echo-with-empty-fallback].
USAGE:
- echo-if-empty [...options] [--] ...
- echo-lines ... | echo-if-empty [...options]
+ echo-with-whitespace-fallback [...options] [--] ...
+ echo-lines ... | echo-with-whitespace-fallback [...options]
OPTIONS:
| --fallback=
@@ -20,23 +21,20 @@ function echo_if_empty() (
EXAMPLE:
- echo-if-empty 'my-fallback-value'
+ echo-with-whitespace-fallback 'my-fallback-value'
my-fallback-value
# exit status: 0
- echo | echo-if-empty 'my-fallback-value' --stdin
+ printf ' \n\t' | echo-with-whitespace-fallback 'my-fallback-value' --stdin
my-fallback-value
# exit status: 0
- echo 'a-value' | echo-if-empty 'my-fallback-value' --stdin
+ printf 'value' | echo-with-whitespace-fallback 'my-fallback-value' --stdin
- 'a-value'
+ value
# exit status: 0
-
- ALTERNATIVES:
- Use [ifne] from [moreutils], which is what we use in [eval-on-empty-stdin] and [eval-on-not-empty-stdin].
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -70,9 +68,9 @@ function echo_if_empty() (
esac
done
- # checck for expected
+ # check for expected
if [[ $option_fallback == "$rand" ]]; then
- help "Missing required argument: "
+ help 'Missing required argument: '
fi
# action
@@ -84,7 +82,7 @@ function echo_if_empty() (
inputs+="$1"$'\n'
}
function on_finish {
- if is-empty-string -- "$inputs"; then
+ if is-whitespace -- "$inputs"; then
__print_string "$fallback"
else
__print_string "$inputs"
@@ -95,5 +93,5 @@ function echo_if_empty() (
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- echo_if_empty "$@"
+ echo_with_whitespace_fallback "$@"
fi
diff --git a/commands.beta/is-empty-directory b/commands.beta/is-empty-directory
deleted file mode 100755
index 6b6a7a64e..000000000
--- a/commands.beta/is-empty-directory
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-
-function is_empty_directory() (
- source "$DOROTHY/sources/bash.bash"
-
- # =====================================
- # Arguments
-
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Checks if the path is an empty directory.
-
- USAGE:
- is-empty-directory [--] ...
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process
- local item option_paths=()
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- '--')
- option_paths+=("$@")
- shift "$#"
- break
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_paths+=("$item") ;;
- esac
- done
-
- # check
- if [[ ${#option_paths[@]} -eq 0 ]]; then
- help "No s provided."
- fi
-
- # =====================================
- # Action
-
- # action
- local path result
- for path in "${option_paths[@]}"; do
- if [[ ! -d $path ]]; then
- return 1
- fi
- result="$(ls -A "$path")"
- if [[ -z $result ]]; then
- continue
- else
- return 1
- fi
- done
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_empty_directory "$@"
-fi
diff --git a/commands.beta/is-even b/commands.beta/is-even
deleted file mode 100755
index f417a170c..000000000
--- a/commands.beta/is-even
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env bash
-
-function is_even() (
- source "$DOROTHY/sources/bash.bash"
-
- # =====================================
- # Arguments
-
- # help
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Checks if the is an even number.
-
- USAGE:
- is-even [...options] [--]
-
- OPTIONS:
-
- Verify this is an even number
-
- RETURNS:
- [0] if all s were odd numbers
- [1] if any s were not odd numbers
- [2] if any s were not numbers
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process
- local item inputs=()
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- '--')
- inputs+=("$@")
- shift $#
- break
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) inputs+=("$item") ;;
- esac
- done
-
- # verify
- if [[ ${#inputs[@]} -eq 0 ]]; then
- help "No s provided"
- fi
-
- # verify
- if ! is-number -- "${inputs[@]}"; then
- return 2
- fi
-
- # =====================================
- # Action
-
- local input
- for input in "${inputs[@]}"; do
- [[ "$((input % 2))" -eq 0 ]] || return # explicit return with [[ required for bash v3
- done
- return 0
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_even "$@"
-fi
diff --git a/commands.beta/is-exec b/commands.beta/is-exec
deleted file mode 100755
index 3e88ad6ba..000000000
--- a/commands.beta/is-exec
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-function is_exec() (
- source "$DOROTHY/sources/bash.bash"
-
- [[ -x $1 ]]
- return
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_exec "$@"
-fi
diff --git a/commands.beta/is-nonempty-file b/commands.beta/is-nonempty-file
index 042a67549..7e80c7726 100755
--- a/commands.beta/is-nonempty-file
+++ b/commands.beta/is-nonempty-file
@@ -1,8 +1,39 @@
#!/usr/bin/env bash
+function is_nonempty_file_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ local dir file
+ dir="$(fs-temp --directory='is-nonempty-file' --directory --touch)"
+ file="$(fs-temp --directory='is-nonempty-file' --file --touch)"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-nonempty-file --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-nonempty-file -- '' ''
+
+ eval-tester --name='missing' --status=9 \
+ -- is-nonempty-file -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='empty dirs' --status=9 \
+ -- is-nonempty-file -- "$dir" "$dir"
+
+ eval-tester --name='empty files' --status=1 \
+ -- is-nonempty-file -- "$file" "$file"
+
+ eval-tester --name='non-empty dir' --status=9 \
+ -- is-nonempty-file -- "$DOROTHY"
+
+ eval-tester --name='non-empty file' \
+ -- is-nonempty-file -- "$DOROTHY/README.md"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_nonempty_file() (
source "$DOROTHY/sources/bash.bash"
- source "$(type -P sudo-helper)"
# =====================================
# Arguments
@@ -10,7 +41,7 @@ function is_nonempty_file() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Checks if is a non-empty file.
+ Checks if a is a file that has contents, aka a file that is not zero-length.
USAGE:
is-nonempty-file [...options] [--] ...
@@ -23,8 +54,10 @@ function is_nonempty_file() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were non-empty files.
- [1] if any s were not a non-empty file.
+ [0] if all s are files that have content.
+ [1] if any s are not a file that has content.
+ [9] if any s are not a file.
+ [22] if empty arguments are provided.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -33,7 +66,7 @@ function is_nonempty_file() (
}
# process
- local item option_paths=() option_sudo='no' option_user='' option_group=''
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -45,44 +78,32 @@ function is_nonempty_file() (
'--user='*) option_user="${item#*=}" ;;
'--group='*) option_group="${item#*=}" ;;
'--')
- option_paths+=("$@")
+ option_inputs+=("$@")
shift "$#"
break
;;
'--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_paths+=("$item") ;;
+ *) option_inputs+=("$item") ;;
esac
done
# check
- if [[ ${#option_paths[@]} -eq 0 ]]; then
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
help "No s provided."
fi
# =====================================
# Action
- function __are_nonempty_files {
- local path
- for path in "$@"; do
- [[ -s $path ]] || return # explicit return with [[ required for bash v3
- done
- return 0
- }
-
- # if need sudo, use visa sudo
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- sudo_helper --inherit --user="$option_user" --group="$option_group" \
- -- __are_nonempty_files "${option_paths[@]}"
- return
- fi
-
- # if don't need sudo, use directly
- __are_nonempty_files "${option_paths[@]}"
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-nonempty-file.bash -- "${option_inputs[@]}"
return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_nonempty_file "$@"
+ if [[ $* == '--test' ]]; then
+ is_nonempty_file_test
+ else
+ is_nonempty_file "$@"
+ fi
fi
diff --git a/commands.beta/is-nonempty-file.bash b/commands.beta/is-nonempty-file.bash
new file mode 100755
index 000000000..fa51e2b5d
--- /dev/null
+++ b/commands.beta/is-nonempty-file.bash
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -f $1 ]]; then
+ # not a file nor symlink to a file
+ exit 9 # EBADF 9 Bad file descriptor
+ fi
+ if [[ ! -s $1 ]]; then
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands.beta/is-root b/commands.beta/is-root
index f119005fc..a9cc6cce6 100755
--- a/commands.beta/is-root
+++ b/commands.beta/is-root
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+# @todo rename to is-root-user or is-user-root
+
function is_root() (
source "$DOROTHY/sources/bash.bash"
diff --git a/commands.beta/is-shapeshifter b/commands.beta/is-shapeshifter
index 8147cb5bd..087ce07ea 100755
--- a/commands.beta/is-shapeshifter
+++ b/commands.beta/is-shapeshifter
@@ -139,7 +139,7 @@ function is_shapeshifter_test() (
)
eval-tester --status=1 -- is-shapeshifter -- "blah" "0123" $'\e[0m'
- eval-tester --status=0 -- is-shapeshifter -- "${inputs[@]}"
+ eval-tester -- is-shapeshifter -- "${inputs[@]}"
echo-style --g1="TEST: $0"
return 0
diff --git a/commands.beta/pdf-decrypt b/commands.beta/pdf-decrypt
index ca476ba6f..55819da1d 100755
--- a/commands.beta/pdf-decrypt
+++ b/commands.beta/pdf-decrypt
@@ -9,13 +9,13 @@ function pdf_decrypt() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Save decrypted copies of the PDF inputs.
+ Take PDF s that have passwords, and save copies that have the passwords removed.
USAGE:
pdf-decrypt [--password=] ...
EXAMPLE:
- pdf-decrypt *.pdf
+ pdf-decrypt -- *.pdf
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -24,43 +24,58 @@ function pdf_decrypt() (
}
# process
- local item files=() password=''
+ local item option_inputs=() option_password=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
- '--password='*) password="${item#*=}" ;;
+ '--password='*) option_password="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
'--'*) help "An unrecognised flag was provided: $item" ;;
- *) files+=("$item") ;;
+ *) option_inputs+=("$item") ;;
esac
done
# =====================================
# Dependencies
- if __command_missing -- qpdf; then
- echo-style --error="[qpdf] is missing, install it first." >/dev/stderr
- return 1
- fi
+ setup-util-qpdf --quiet
# =====================================
# Act
- local input output current_password
- for input in "${files[@]}"; do
- output="$(fs-filename -- "$input") [decrypted].pdf"
- current_password="$(
- ask --required --password \
- --question="Enter the password for $input" \
- --default="$password"
- )"
+ local index filepath filename
+ local filenames=()
+ for index in "${!option_inputs[@]}"; do
+ filepath="${option_inputs[index]}"
+ filename="$(fs-filename -- "$filepath")"
+ filenames[index]="$filename"
+ done
+
+ local password
+ password="$(
+ ask --required --password \
+ --question='Enter the decryption password for the PDFs' \
+ --question="$(echo-lines --columns -- "${filenames[@]}")" \
+ --default="$option_password"
+ )"
+
+ local outpath
+ for index in "${!option_inputs[@]}"; do
+ filepath="${option_inputs[index]}"
+ filename="${filenames[index]}"
+ outpath="$item [decrypted].pdf"
eval-helper --quiet \
- --pending="$(echo-style --bold="Decrypting " --code="$input" --bold=" to " --code="$output")" \
- --success="$(echo-style --bold+green="Decrypted " --code="$input" --bold=" to " --code="$output")" \
- --failure="$(echo-style --bold+red="Failed to decrypt " --code="$input" --bold=" to " --code="$output")" \
- -- qpdf -password="$current_password" -decrypt "$input" "$output" || :
+ --pending="$(echo-style --bold='Decrypting ' --code="$filepath" --bold=' to ' --code="$outpath")" \
+ --success="$(echo-style --bold+green='Decrypted ' --code="$filepath" --bold=' to ' --code="$outpath")" \
+ --failure="$(echo-style --bold+red='Failed to decrypt ' --code="$filepath" --bold=' to ' --code="$outpath")" \
+ -- qpdf -password="$password" -decrypt "$filepath" "$outpath" || :
done
)
diff --git a/commands.beta/rm-vmware b/commands.beta/rm-vmware-fusion
similarity index 96%
rename from commands.beta/rm-vmware
rename to commands.beta/rm-vmware-fusion
index 2880e3c27..b6b42c6f2 100755
--- a/commands.beta/rm-vmware
+++ b/commands.beta/rm-vmware-fusion
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-function rm_vmware() (
+function setup_util_vmware_fusion() (
source "$DOROTHY/sources/bash.bash"
local paths=(
@@ -61,5 +61,5 @@ function rm_vmware() (
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- rm_vmware "$@"
+ setup_util_vmware_fusion "$@"
fi
diff --git a/commands.deprecated/echo-if-empty b/commands.deprecated/echo-if-empty
new file mode 100755
index 000000000..5f1466db5
--- /dev/null
+++ b/commands.deprecated/echo-if-empty
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+function echo_if_empty() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='echo-if-empty' --bold=' has been deprecated in favor of ' --code='echo-with-whitespace-fallback'
+
+ # =====================================
+ # Action
+
+ is-not-whitespace "$@"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ echo_if_empty "$@"
+fi
diff --git a/commands.deprecated/fs-size b/commands.deprecated/fs-size
new file mode 100755
index 000000000..5d74daaf9
--- /dev/null
+++ b/commands.deprecated/fs-size
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+function fs_size() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='fs-size' --bold=' has been deprecated in favor of ' --code='fs-structure' --bold=' or ' --code='get-size'
+
+ # =====================================
+ # Action
+
+ fs-structure "$@"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ fs_size "$@"
+fi
diff --git a/commands/get-array-count b/commands.deprecated/get-array-count
similarity index 88%
rename from commands/get-array-count
rename to commands.deprecated/get-array-count
index a9d54c6d3..4ad55954c 100755
--- a/commands/get-array-count
+++ b/commands.deprecated/get-array-count
@@ -4,6 +4,7 @@
function get_array_count() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='get-array-count' --bold=' has been deprecated in favor of ' --code='echo-trim-empty-lines'
# =====================================
# Arguments
@@ -49,7 +50,7 @@ function get_array_count() (
local input
for input in "${option_inputs[@]}"; do
- if is-empty-string -- "$input"; then
+ if is-whitespace -- "$input"; then
__print_lines '-1'
return 1
fi
diff --git a/commands.beta/get-line-count b/commands.deprecated/get-line-count
similarity index 88%
rename from commands.beta/get-line-count
rename to commands.deprecated/get-line-count
index 9d1e5b558..40f4fbd57 100755
--- a/commands.beta/get-line-count
+++ b/commands.deprecated/get-line-count
@@ -4,6 +4,7 @@
function get_line_count() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='get-line-count' --bold=' has been deprecated in favor of ' --code='echo-count-lines'
# =====================================
# Arguments
diff --git a/commands/is-array-count b/commands.deprecated/is-array-count
similarity index 87%
rename from commands/is-array-count
rename to commands.deprecated/is-array-count
index dc48aa370..6173a8fbf 100755
--- a/commands/is-array-count
+++ b/commands.deprecated/is-array-count
@@ -2,6 +2,7 @@
function is_array_count() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-count' --bold=' has been deprecated in favor of ' --code='echo-trim-empty-lines'
# =====================================
# Arguments
@@ -65,11 +66,8 @@ function is_array_count() (
# =====================================
# Action
- if [[ "$(get-array-count -- "${option_inputs[@]}")" -eq $option_size ]]; then
- return 0
- else
- return 1
- fi
+ [[ "$(get-array-count -- "${option_inputs[@]}")" -eq $option_size ]]
+ return
)
# fire if invoked standalone
diff --git a/commands/is-array-count-ge b/commands.deprecated/is-array-count-ge
similarity index 92%
rename from commands/is-array-count-ge
rename to commands.deprecated/is-array-count-ge
index 919dc4a46..bffbe0023 100755
--- a/commands/is-array-count-ge
+++ b/commands.deprecated/is-array-count-ge
@@ -2,6 +2,7 @@
function is_array_count_ge() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-count-ge' --bold=' has been deprecated in favor of ' --code='echo-trim-empty-lines'
# =====================================
# Arguments
diff --git a/commands/is-array-empty b/commands.deprecated/is-array-empty
similarity index 90%
rename from commands/is-array-empty
rename to commands.deprecated/is-array-empty
index 745fdc7ff..7646cbf55 100755
--- a/commands/is-array-empty
+++ b/commands.deprecated/is-array-empty
@@ -11,6 +11,7 @@
function is_array_empty() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-empty' --bold=' has been deprecated in favor of ' --code='is-whitespace'
# =====================================
# Arguments
@@ -63,7 +64,7 @@ function is_array_empty() (
local input
for input in "${option_inputs[@]}"; do
- if is-nonempty-string -- "$input"; then
+ if is-not-whitespace -- "$input"; then
return 1
fi
done
diff --git a/commands/is-array-empty-or-partial b/commands.deprecated/is-array-empty-or-partial
similarity index 86%
rename from commands/is-array-empty-or-partial
rename to commands.deprecated/is-array-empty-or-partial
index 5eaf51fe9..74acb9db8 100755
--- a/commands/is-array-empty-or-partial
+++ b/commands.deprecated/is-array-empty-or-partial
@@ -7,6 +7,7 @@
function is_array_empty_or_partial() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-empty-or-partial' --bold=' has been deprecated in favor of ' --code='is-whitespace' --bold=' and ' --code='is-not-whitespace'
# =====================================
# Arguments
@@ -63,7 +64,7 @@ function is_array_empty_or_partial() (
local input
for input in "${option_inputs[@]}"; do
- if is-empty-string -- "$input"; then
+ if is-whitespace -- "$input"; then
return 0
fi
done
diff --git a/commands/is-array-full b/commands.deprecated/is-array-full
similarity index 89%
rename from commands/is-array-full
rename to commands.deprecated/is-array-full
index 135769285..e9fe7a892 100755
--- a/commands/is-array-full
+++ b/commands.deprecated/is-array-full
@@ -7,6 +7,7 @@
function is_array_full() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-full' --bold=' has been deprecated in favor of ' --code='is-not-whitespace'
# =====================================
# Arguments
@@ -63,7 +64,7 @@ function is_array_full() (
local input
for input in "${option_inputs[@]}"; do
- if is-empty-string -- "$input"; then
+ if is-whitespace -- "$input"; then
return 1
fi
done
diff --git a/commands/is-array-full-or-partial b/commands.deprecated/is-array-full-or-partial
similarity index 86%
rename from commands/is-array-full-or-partial
rename to commands.deprecated/is-array-full-or-partial
index e511c2db1..39697134f 100755
--- a/commands/is-array-full-or-partial
+++ b/commands.deprecated/is-array-full-or-partial
@@ -7,6 +7,7 @@
function is_array_full_or_partial() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-full-or-partial' --bold=' has been deprecated in favor of ' --code='is-whitespace' --bold=' and ' --code='is-not-whitespace'
# =====================================
# Arguments
@@ -59,7 +60,7 @@ function is_array_full_or_partial() (
local input
for input in "${option_inputs[@]}"; do
- if is-nonempty-string -- "$input"; then
+ if is-not-whitespace -- "$input"; then
return 0
fi
done
diff --git a/commands/is-array-partial b/commands.deprecated/is-array-partial
similarity index 72%
rename from commands/is-array-partial
rename to commands.deprecated/is-array-partial
index 39cc593bb..df262c4f0 100755
--- a/commands/is-array-partial
+++ b/commands.deprecated/is-array-partial
@@ -8,6 +8,7 @@
function is_array_partial() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-array-partial' --bold=' has been deprecated in favor of ' --code='is-whitespace' --bold=' and ' --code='is-not-whitespace'
# =====================================
# Arguments
@@ -58,15 +59,15 @@ function is_array_partial() (
# =====================================
# Action
- local input has_empty='no' has_nonempty='no'
+ local input had_empty_string='no' had_nonempty_string='no'
for input in "${option_inputs[@]}"; do
- if [[ $has_empty == 'no' ]] && is-empty-string -- "$input"; then
- has_empty='yes'
+ if [[ $had_empty_string == 'no' ]] && is-whitespace -- "$input"; then
+ had_empty_string='yes'
fi
- if [[ $has_nonempty == 'no' ]] && is-nonempty-string -- "$input"; then
- has_nonempty='yes'
+ if [[ $had_nonempty_string == 'no' ]] && is-not-whitespace -- "$input"; then
+ had_nonempty_string='yes'
fi
- if [[ $has_empty == 'yes' && $has_nonempty == 'yes' ]]; then
+ if [[ $had_empty_string == 'yes' && $had_nonempty_string == 'yes' ]]; then
return 0
fi
done
diff --git a/commands.deprecated/is-dir b/commands.deprecated/is-dir
index 814ff7ca5..30b2193dc 100755
--- a/commands.deprecated/is-dir
+++ b/commands.deprecated/is-dir
@@ -4,6 +4,9 @@ function is_dir() (
source "$DOROTHY/sources/bash.bash"
dorothy-warnings add --code='is-dir' --bold=' has been deprecated in favor of ' --code='is-directory'
+ # =====================================
+ # Action
+
local dir="$1"
[[ -d $dir ]]
return
diff --git a/commands.beta/is-either b/commands.deprecated/is-either
similarity index 63%
rename from commands.beta/is-either
rename to commands.deprecated/is-either
index 826bcdb47..6bd9acf08 100755
--- a/commands.beta/is-either
+++ b/commands.deprecated/is-either
@@ -2,6 +2,10 @@
function is_either() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-either' --bold=' has been deprecated in favor of ' --code='is-needle'
+
+ # =====================================
+ # Action
local arg
for arg in "${@:2}"; do
diff --git a/commands.deprecated/is-empty-ls b/commands.deprecated/is-empty-ls
new file mode 100755
index 000000000..990ca4c7a
--- /dev/null
+++ b/commands.deprecated/is-empty-ls
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+function is_empty_ls() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-empty-ls' --bold=' has been deprecated in favor of ' --code='is-empty-directory'
+
+ # =====================================
+ # Action
+
+ is-empty-directory "$@"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ is_empty_ls "$@"
+fi
diff --git a/commands.deprecated/is-empty-string b/commands.deprecated/is-empty-string
new file mode 100755
index 000000000..19062aab9
--- /dev/null
+++ b/commands.deprecated/is-empty-string
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+function is_empty_string() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-empty-string' --bold=' has been deprecated in favor of ' --code='is-whitespace'
+
+ # =====================================
+ # Action
+
+ is-whitespace "$@"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ is_empty_string "$@"
+fi
diff --git a/commands.beta/is-equal b/commands.deprecated/is-equal
similarity index 65%
rename from commands.beta/is-equal
rename to commands.deprecated/is-equal
index 129ac3d05..87524f916 100755
--- a/commands.beta/is-equal
+++ b/commands.deprecated/is-equal
@@ -2,6 +2,7 @@
function is_equal() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-equal' --bold=' has been deprecated in favor of ' --code='test .. = ..'
[[ $1 == "$2" ]]
return
diff --git a/commands.deprecated/is-exec b/commands.deprecated/is-exec
new file mode 100755
index 000000000..a20e7f344
--- /dev/null
+++ b/commands.deprecated/is-exec
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+function is_exec() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-exec' --bold=' has been deprecated until there is a need for it, in which case it will be renamed to ' --code='is-executable' --bold=' and will support multiple arguments'
+
+ # =====================================
+ # Action
+
+ [[ -x $1 ]]
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ is_exec "$@"
+fi
diff --git a/commands.deprecated/is-match b/commands.deprecated/is-match
index 880843f15..f6d771152 100755
--- a/commands.deprecated/is-match
+++ b/commands.deprecated/is-match
@@ -4,10 +4,10 @@ function is_match_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --name='match works' --status=0 \
+ eval-tester --name='match works' \
-- is-match 'a +haystack ?' 'a haystack'
- eval-tester --name='match works' --status=0 \
+ eval-tester --name='match works' \
-- is-match -i 'Z|B' 'abc'
eval-tester --name='no match works' --status=1 \
diff --git a/commands.beta/is-neither b/commands.deprecated/is-neither
similarity index 63%
rename from commands.beta/is-neither
rename to commands.deprecated/is-neither
index 04010507c..1a79b2999 100755
--- a/commands.beta/is-neither
+++ b/commands.deprecated/is-neither
@@ -2,6 +2,10 @@
function is_neither() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-either' --bold=' has been deprecated in favor of ' --code='! is-needle'
+
+ # =====================================
+ # Action
local arg
for arg in "${@:2}"; do
diff --git a/commands.deprecated/is-nonempty-string b/commands.deprecated/is-nonempty-string
new file mode 100755
index 000000000..c5b625857
--- /dev/null
+++ b/commands.deprecated/is-nonempty-string
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+function is_nonempty_string() (
+ source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='is-nonempty-string' --bold=' has been deprecated in favor of ' --code='is-not-whitespace'
+
+ # =====================================
+ # Action
+
+ is-not-whitespace "$@"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ is_nonempty_string "$@"
+fi
diff --git a/commands/rm-junk b/commands.deprecated/rm-junk
similarity index 70%
rename from commands/rm-junk
rename to commands.deprecated/rm-junk
index 2f0999323..727965a80 100755
--- a/commands/rm-junk
+++ b/commands.deprecated/rm-junk
@@ -2,6 +2,7 @@
function rm_junk() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='rm-junk' --bold=' has been deprecated in favor of ' --code='fs-trim --junk'
# =====================================
# Arguments
@@ -57,33 +58,8 @@ function rm_junk() (
# =====================================
# Action
- # prepare the variables we will use
- local path find_args=() action_args=()
- local ds_store_args=(
- '(' -name '.DS_Store' -or -name '._.DS_Store' ')'
- )
- local empty_args=(
- '(' -type d -empty ')'
- )
-
- # add DS_Store args, and empty args if desired
- find_args+=("${ds_store_args[@]}")
- if [[ $option_empty == 'yes' ]]; then
- find_args+=(
- -or
- "${empty_args[@]}"
- )
- fi
-
- # wrap the find args, and add the actions
- action_args+=(
- '(' "${find_args[@]}" ')' -delete -print
- )
-
- # perform the find action on each path
- for path in "${option_paths[@]}"; do
- find "$path" "${action_args[@]}"
- done
+ fs-trim --junk --empty-directories="$option_empty" -- "$path"
+ return
)
# fire if invoked standalone
diff --git a/commands/rm-modules b/commands.deprecated/rm-modules
similarity index 87%
rename from commands/rm-modules
rename to commands.deprecated/rm-modules
index 3ca638003..bd29593e5 100755
--- a/commands/rm-modules
+++ b/commands.deprecated/rm-modules
@@ -3,6 +3,7 @@
function rm_modules() (
source "$DOROTHY/sources/bash.bash"
__require_globstar
+ dorothy-warnings add --code='rm-modules' --bold=' has been deprecated in favor of ' --code='fs-trim --junk'
# =====================================
# Arguments
@@ -52,10 +53,8 @@ function rm_modules() (
# =====================================
# Action
- local path
- for path in "${option_paths[@]}"; do
- fs-rm --no-confirm --optional -- "$path"/**/{node_modules,pnp,package-lock.json,yarn.lock,.pnp.js,.log}
- done
+ fs-trim --junk --empty-directories="$option_empty" -- "$path"
+ return
)
# fire if invoked standalone
diff --git a/commands.beta/rm-svn b/commands.deprecated/rm-svn
similarity index 87%
rename from commands.beta/rm-svn
rename to commands.deprecated/rm-svn
index 8189f9434..ee2534d25 100755
--- a/commands.beta/rm-svn
+++ b/commands.deprecated/rm-svn
@@ -2,6 +2,7 @@
function rm_svn() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='rm-svn' --bold=' has been deprecated in favor of ' --code='find -name .svn -delete -print'
# =====================================
# Arguments
diff --git a/commands.beta/rm-sync b/commands.deprecated/rm-sync
similarity index 87%
rename from commands.beta/rm-sync
rename to commands.deprecated/rm-sync
index 3b692217c..6fa2ae55c 100755
--- a/commands.beta/rm-sync
+++ b/commands.deprecated/rm-sync
@@ -2,6 +2,7 @@
function rm_sync() (
source "$DOROTHY/sources/bash.bash"
+ dorothy-warnings add --code='rm-sync' --bold=' has been deprecated in favor of ' --code='find -name .sync -delete -print'
# =====================================
# Arguments
diff --git a/commands/choose b/commands/choose
index 2ab3b7602..401c507a3 100755
--- a/commands/choose
+++ b/commands/choose
@@ -516,8 +516,11 @@ function choose_() (
--[no-]confirm-input=[yes|NO]
Have the choose menu confirm the user's input (their selection or lack of selection). Defaults to disabled.
+ --[no-]confirm-cancel=[YES|no]
+ Have the cancel menu confirm the user's cancellation (whether it will revert to nothing when not required, or to the default if provided and required). Defaults to enabled.
+
--[no-]confirm=[yes|no]
- HAve the prompt not skip any step, requiring solo values to be prompted, default values to be prompted, and selections or their lack of to be confirmed.
+ Have the prompt not skip any step, requiring solo values to be prompted, default values to be prompted, cancellations to be prompted, and selections or their lack of to be confirmed.
--[no-]required=[yes|NO]
Do not continue until a selection is made. Disable aborting the prompt.
@@ -535,7 +538,7 @@ function choose_() (
Custom timeout value in seconds.
QUIRKS:
- If you wish to return the index, which is desirable in the case of when multiple values can be identical, use --index or --return='\$INDEX'.
+ If you wish to return the index, which is desirable in the case of when multiple values can be identical, use [--index].
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -547,7 +550,7 @@ function choose_() (
local item='' inputs=() tmp=()
local option_question=()
local option_label='no' option_visual='' option_return='$VALUE'
- local defaults_exact=() defaults_fuzzy=() option_confirm_solo='yes' option_confirm_default='yes' option_confirm_input='no'
+ local defaults_exact=() defaults_fuzzy=() option_confirm_solo='yes' option_confirm_default='yes' option_confirm_input='no' option_confirm_cancel='yes'
local option_required='no' option_multi='no'
local option_linger='no' option_timeout=''
while [[ $# -ne 0 ]]; do
@@ -588,10 +591,14 @@ function choose_() (
'--no-confirm-input'* | '--confirm-input'*)
option_confirm_input="$(get-flag-value --affirmative --fallback="$option_confirm_input" -- "$item")"
;;
+ '--no-confirm-cancel'* | '--confirm-cancel'*)
+ option_confirm_cancel="$(get-flag-value --affirmative --fallback="$option_confirm_cancel" -- "$item")"
+ ;;
'--no-confirm'* | '--confirm'*)
option_confirm_solo="$(get-flag-value --affirmative --fallback="$option_confirm_solo" -- "$item")"
option_confirm_default="$(get-flag-value --affirmative --fallback="$option_confirm_default" -- "$item")"
option_confirm_input="$(get-flag-value --affirmative --fallback="$option_confirm_input" -- "$item")"
+ option_confirm_cancel="$(get-flag-value --affirmative --fallback="$option_confirm_cancel" -- "$item")"
;;
'--no-required'* | '--required'*)
option_required="$(get-flag-value --affirmative --fallback="$option_required" -- "$item")"
@@ -794,6 +801,19 @@ function choose_() (
if [[ $option_confirm_default == 'no' ]]; then
can_skip_prompt='yes'
fi
+ # adjust fallbacks for single vs multi mode
+ # fallbacks=(...) not actually needed, as never used
+ if [[ $option_required == 'yes' ]]; then
+ if [[ $option_multi == 'no' ]]; then
+ fallbacks_count=1
+ fallbacks_indexes=("${defaults_indexes[0]}")
+ fallbacks_last=0
+ else
+ fallbacks_count="$defaults_count"
+ fallbacks_indexes=("${defaults_indexes[@]}")
+ fallbacks_last="$defaults_last"
+ fi
+ fi
else
can_revert_to_defaults='no'
if [[ $option_required == 'no' ]]; then
@@ -803,18 +823,6 @@ function choose_() (
fi
fi
- # adjust fallbacks for single vs multi mode
- # fallbacks=(...) not actually needed, as never used
- if [[ $option_multi == 'no' && $defaults_count -gt 1 ]]; then
- fallbacks_count=1
- fallbacks_indexes=("${defaults_indexes[0]}")
- fallbacks_last=0
- else
- fallbacks_count="$defaults_count"
- fallbacks_indexes=("${defaults_indexes[@]}")
- fallbacks_last="$defaults_last"
- fi
-
# prepare menu vars
local \
commentary='' \
@@ -987,7 +995,7 @@ function choose_() (
if [[ $can_revert_to_defaults == 'yes' ]]; then
add_legend_keys 'legend_choose' 'NEXT PREF' 'TAB' # next preference
add_legend_keys 'legend_choose' 'PREV PREF' '⇧ TAB' # prior preference
- add_legend_keys 'legend_choose' 'RESET' 'Z' # reset preferences
+ add_legend_keys 'legend_choose' 'RESET' 'Z' 'R' # reset preferences
if [[ $option_multi == 'yes' ]]; then
add_legend_keys 'legend_choose' 'ALL/NONE' 'T'
fi
@@ -1211,6 +1219,9 @@ function choose_() (
menu_cursor_confirm_and_cancel=0
fi
}
+ function select_index {
+ select_only_index "$1"
+ }
function select_defaults {
# select only first preference
if [[ $defaults_count -ne 0 ]]; then
@@ -1237,6 +1248,14 @@ function choose_() (
select_none
select_defaults
}
+ function action_fallbacks {
+ if [[ $fallbacks_count -eq 0 ]]; then
+ select_none
+ else
+ select_none
+ select_index "${fallbacks_indexes[@]}"
+ fi
+ }
function action_jump {
local index="$1"
# jump to number
@@ -1983,10 +2002,13 @@ function choose_() (
elif [[ $menu_mode == 'cancel' ]]; then
# CANCEL MENU
if [[ $key =~ ^(enter|e)$ || ($key == 'space' && $option_multi == 'no') ]]; then
- action_revert
+ action_fallbacks
set_menu_mode 'confirmed'
break
elif [[ $key =~ ^(escape|q)$ ]]; then
+ if [[ $option_multi == 'no' ]]; then
+ action_revert
+ fi
set_menu_mode 'choose'
fi
elif [[ $menu_mode == 'confirm' ]]; then
@@ -2009,11 +2031,12 @@ function choose_() (
break
fi
fi
- elif [[ $can_cancel == 'yes' && $key =~ ^(escape|q)^ ]]; then
- if [[ $option_confirm_input == 'yes' ]]; then
+ elif [[ $can_cancel == 'yes' && $key =~ ^(escape|q)$ ]]; then
+ if [[ $option_confirm_cancel == 'yes' ]]; then
+ # note that selection has no impact on cancel, as cancel's behaviour for rendering is hard coded
set_menu_mode 'cancel'
else
- action_revert
+ action_fallbacks
set_menu_mode 'confirmed'
break
fi
@@ -2027,7 +2050,7 @@ function choose_() (
set_menu_mode 'confirmed'
break
fi
- elif [[ $key == 'z' ]]; then
+ elif [[ $key =~ ^(z|r)$ ]]; then
action_revert
elif [[ $option_multi == 'yes' ]]; then
if [[ $key == 't' ]]; then
diff --git a/commands/command-exists b/commands/command-exists
index 0d456a643..981b5b1cd 100755
--- a/commands/command-exists
+++ b/commands/command-exists
@@ -10,10 +10,10 @@ function command_exists_test() (
eval-tester --status=1 \
-- command-exists -- this-is-a-non-existent-command command-exists
- eval-tester --status=0 \
+ eval-tester \
-- command-exists -- command-exists
- eval-tester --status=0 \
+ eval-tester \
-- command-exists -- command-exists command-missing
echo-style --g1="TEST: $0"
@@ -35,7 +35,7 @@ function command_exists() (
RETURNS:
[0] if all commands are available
- [1] if any command was not available
+ [1] if any command is not available
QUIRKS:
Returns on first failure.
diff --git a/commands/command-missing b/commands/command-missing
index da0df82f1..66d976a8a 100755
--- a/commands/command-missing
+++ b/commands/command-missing
@@ -4,10 +4,10 @@ function command_missing_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --status=0 \
+ eval-tester \
-- command-missing -- this-is-a-non-existent-command
- eval-tester --status=0 \
+ eval-tester \
-- command-missing -- this-is-a-non-existent-command command-missing
eval-tester --status=1 \
@@ -35,7 +35,7 @@ function command_missing() (
RETURNS:
[0] if ANY command is missing.
- [1] if ALL commands were present.
+ [1] if all commands are present.
QUIRKS:
Returns on first failure.
diff --git a/commands/command-working b/commands/command-working
index c9d4c7b82..0f4514e46 100755
--- a/commands/command-working
+++ b/commands/command-working
@@ -10,10 +10,10 @@ function command_working_test() (
eval-tester --status=3 --stderr="< 'this-is-a-non-existent-command' />[3] not working because it is missing" \
-- env COLOR=no command-working -- this-is-a-non-existent-command command-missing
- eval-tester --status=0 \
+ eval-tester \
-- command-working -- command-exists
- eval-tester --status=0 \
+ eval-tester \
-- command-working -- command-exists command-missing
echo-style --g1="TEST: $0"
diff --git a/commands/contains-line b/commands/contains-line
index 1529f0364..ee2a68107 100755
--- a/commands/contains-line
+++ b/commands/contains-line
@@ -31,8 +31,8 @@ function contains_line() (
echo-lines -- 'one' '' 'three' | contains-line --needle='' # success
RETURNS:
- [0] if an line contained a line.
- [1] if no lines were a line.
+ [0] if ANY line are a line.
+ [1] if all lines are not a line.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/dorothy b/commands/dorothy
index 25f6b845f..c301ee190 100755
--- a/commands/dorothy
+++ b/commands/dorothy
@@ -836,12 +836,6 @@ function dorothy_() (
--success="$(echo-style --success='Staged changed files.')" \
--failure="$(echo-style --error='Failed to stage changed files.')" \
-- stage_changed_files "$DOROTHY"
-
- eval_helper --quiet --no-wrap \
- --pending="$(echo-style --bold='Removing junk files...')" \
- --success="$(echo-style --success='Removed junk files.')" \
- --failure="$(echo-style --error='Failed to remove junk files.')" \
- -- rm-junk "$DOROTHY"
}
function ensure_dorothy_configured {
diff --git a/commands/down b/commands/down
index 440334088..52428cefd 100755
--- a/commands/down
+++ b/commands/down
@@ -181,13 +181,13 @@ function down_() (
if [[ -n $archive_format || -n $archive_glob ]]; then
local url_basename
url_basename="$(basename "$url" | echo-trim-special --stdin)"
- download_directory="$(fs-temp --directory='down' --directory)"
+ download_directory="$(fs-temp --directory='down' --directory --touch)"
download_file="$url_basename"
else
download_directory="$directory"
- download_file="$file" # can be empty
+ download_file="$file" # can be empty
+ __mkdirp "$download_directory" # fs-temp makes directory
fi
- __mkdirp "$download_directory"
# tool helpers
function do_aria2c {
diff --git a/commands/echo-if-file b/commands/echo-if-file
index f84da89cd..bdf454736 100755
--- a/commands/echo-if-file
+++ b/commands/echo-if-file
@@ -9,7 +9,7 @@ function echo_if_file() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Output inputs that are files.
+ Output inputs that are files (or symlinks to files).
USAGE:
echo-if-file [...options] [--] ...
diff --git a/commands/echo-regexp b/commands/echo-regexp
index 41e825c4a..514a5bed6 100755
--- a/commands/echo-regexp
+++ b/commands/echo-regexp
@@ -12,7 +12,7 @@ function echo_regexp_test() (
eval-tester --name='match works' --stdout='b' \
-- echo-regexp -i 'Z|B' -- 'abc'
- eval-tester --name='no match works' --status=0 \
+ eval-tester --name='no match works' \
-- echo-regexp 'Z|Y' -- 'abc'
eval-tester --name='no match fails with -q' --status=1 \
@@ -90,10 +90,10 @@ function echo_regexp_test() (
# --------
- eval-tester --name='character classes [[:XXX:]]' --status=0 \
+ eval-tester --name='character classes [[:XXX:]]' \
-- echo-regexp -q '^[[:digit:]]+$' -- '012'
- eval-tester --name='character classes [[:XXX:][:YYY:]]' --status=0 \
+ eval-tester --name='character classes [[:XXX:][:YYY:]]' \
-- echo-regexp -q '^[[:digit:][:lower:]]+$' -- 'z0'
# --------
diff --git a/commands/echo-trim-empty-lines b/commands/echo-trim-empty-lines
index 8311eb1ba..33d72dcd6 100755
--- a/commands/echo-trim-empty-lines
+++ b/commands/echo-trim-empty-lines
@@ -10,6 +10,7 @@ function echo_trim_empty_lines() (
cat <<-EOF >/dev/stderr
ABOUT:
Trims empty lines from .
+ Companion to [is-not-whitespace], [is-whitespace]. Equivalent to a [echo-strings], [echo-nonempty-strings].
USAGE:
echo-trim-empty-lines [...options] [--] ...
@@ -43,7 +44,7 @@ function echo_trim_empty_lines() (
# Action
function on_line {
- if is-nonempty-string -- "$1"; then
+ if is-not-whitespace -- "$1"; then
__print_lines "$1"
fi
}
diff --git a/commands/echo-trim-padding b/commands/echo-trim-padding
index 20363f76a..48cc10fe6 100755
--- a/commands/echo-trim-padding
+++ b/commands/echo-trim-padding
@@ -41,7 +41,7 @@ function echo_trim_padding() (
# this allows data to be echoed as it is received
local queue=() started='no'
function on_line {
- if is-empty-string -- "$1"; then
+ if is-whitespace -- "$1"; then
if [[ $started == 'yes' ]]; then
queue+=("$1")
fi
diff --git a/commands.beta/echo-values b/commands/echo-values
similarity index 80%
rename from commands.beta/echo-values
rename to commands/echo-values
index 6b08c4b35..d3bf9f37a 100755
--- a/commands.beta/echo-values
+++ b/commands/echo-values
@@ -7,7 +7,8 @@ function echo_values() (
cat <<-EOF >/dev/stderr
ABOUT:
Output each input, that is a value, onto its own line.
- Uses [is-value] for the internal check.
+ Use to trim empty values from a list.
+ Companion to [is-value], [is-empty-value]. Equivalent to a [echo-nonempty-values], [echo-non-nullish], [echo-not-nullish].
USAGE:
echo-values [...options] [--] ...
@@ -31,7 +32,7 @@ function echo_values() (
[7] = [z]
# trimming using echo-values
- echo-lines -- '' 0 a NULL VOID UNDEFINED false z | echo-values --stdin | echo-verbose --stdin
+ echo-values -- '' 0 a NULL VOID UNDEFINED false z | echo-verbose --stdin
[0] = [0]
[1] = [a]
diff --git a/commands/eval-helper b/commands/eval-helper
index 6f78f2913..7579d6f32 100755
--- a/commands/eval-helper
+++ b/commands/eval-helper
@@ -105,10 +105,11 @@ function eval_helper() (
# Action
# terminal
- local terminal_device_file="$option_terminal_device_file"
+ local terminal_device_file="$option_terminal_device_file" output_device_file
if [[ -z $terminal_device_file ]]; then
terminal_device_file="$(get-terminal-device-file)"
fi
+ output_device_file="$terminal_device_file"
# element
local element_open=''
@@ -123,10 +124,19 @@ function eval_helper() (
# confirm
if [[ $option_confirm == 'yes' ]] && ! confirm --positive --ppid=$$ -- 'Confirm execution of the command that is below:' "$element_open"; then
- echo-style --notice='Skipped execution of:' ' ' "$element_open"
+ echo-style --notice1='Skipped execution of:' --code-notice1="$element_open" >"$terminal_device_file"
return 0
fi
+ # output
+ local output=''
+ function flush_output {
+ if [[ -n $output ]]; then
+ __print_string "$output" >"$output_device_file"
+ output=''
+ fi
+ }
+
# headers
local header=''
if [[ -n $option_pending ]]; then
@@ -134,20 +144,13 @@ function eval_helper() (
fi
if [[ $option_wrap == 'yes' ]]; then
header+="$element_open"$'\n'
+ output_device_file='/dev/stdout'
fi
if [[ -n $header ]]; then
- __print_string "$header" >"$terminal_device_file"
+ output="$header"
+ flush_output
fi
- # output
- local output=''
- function flush_output {
- if [[ -n $output ]]; then
- __print_string "$output" >"$terminal_device_file"
- output=''
- fi
- }
-
# output everything if already inside a revolving door, or if in verbose mode
local cmd_status=0
if [[ ${INSIDE_REVOLVING_DOOR-} == 'yes' || $option_quiet == 'no' ]]; then
diff --git a/commands/fs-dequarantine b/commands/fs-dequarantine
index de6b4dd6a..b6e2822d7 100755
--- a/commands/fs-dequarantine
+++ b/commands/fs-dequarantine
@@ -9,7 +9,7 @@ function fs_dequarantine() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Remove the quarantine flag from a path.
+ Remove the quarantine flag from a path.
USAGE:
fs-dequarantine [--] ...
diff --git a/commands/fs-filename b/commands/fs-filename
index 4444615b2..46f8fd9d9 100755
--- a/commands/fs-filename
+++ b/commands/fs-filename
@@ -12,11 +12,14 @@ function fs_filename() (
Gets the filename of a path.
USAGE:
- fs-filename [--first] [--basename] [--] ...
+ fs-filename [...options] [--] ...
- FLAGS:
- --first If the filename has multiple extensions, only the first part is returned.
- --basename If a path was returned, only work with the basename.
+ OPTIONS:
+ --first
+ If the filename has multiple extensions, only the first part is returned.
+
+ --basename
+ If a path was returned, only work with the basename.
EXAMPLES:
fs-filename -- a.b.c
diff --git a/commands/fs-realpath b/commands/fs-realpath
index 463931c0f..b70171720 100755
--- a/commands/fs-realpath
+++ b/commands/fs-realpath
@@ -33,6 +33,12 @@ function fs_realpath() (
--relative-base=
If provided, print absolute paths unless paths below DIR
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
QUIRKS:
If you don't care about symlinks, you should prefer to use [fs-absolute] instead as it is simpler.
Use [--resolve --broken --relative] to help you repair broken relative symlinks.
@@ -44,7 +50,7 @@ function fs_realpath() (
}
# options
- local item option_paths=() option_resolve='yes' option_validate='yes' option_relative='no' option_relative_to='' option_relative_base=''
+ local item option_paths=() option_resolve='yes' option_validate='yes' option_relative='no' option_relative_to='' option_relative_base='' option_sudo='no' option_user='' option_group=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -63,6 +69,11 @@ function fs_realpath() (
option_relative="$(get-flag-value --affirmative --fallback="$option_relative" -- "$item")"
;;
'--path='*) option_paths+=("${item#*=}") ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
'--')
option_paths+=("$@")
shift $#
@@ -81,6 +92,10 @@ function fs_realpath() (
# =====================================
# Action
+ function __sudo {
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" "$@"
+ }
+
function do_gnu_realpath {
local gnu_realpath
if __command_exists -- grealpath; then
@@ -141,7 +156,8 @@ function fs_realpath() (
fi
# execute
- "$gnu_realpath" "${args[@]}" "$path"
+ __sudo -- \
+ "$gnu_realpath" "${args[@]}" "$path"
}
function do_gnu_readlink {
# don't support unsupported args
@@ -194,13 +210,13 @@ function fs_realpath() (
# unless canoniclizing, then symlinks are required
return 45 # ENOTSUP 45 Operation not supported
else
- "$gnu_readlink" "$path"
+ __sudo -- "$gnu_readlink" "$path"
fi
else
if [[ $option_validate == 'yes' ]]; then
- "$gnu_readlink" --canonicalize-existing "$path"
+ __sudo -- "$gnu_readlink" --canonicalize-existing "$path"
else
- "$gnu_readlink" --canonicalize-missing "$path"
+ __sudo -- "$gnu_readlink" --canonicalize-missing "$path"
fi
fi
}
@@ -233,15 +249,15 @@ function fs_realpath() (
# -f fetches the absolutely resolved path
if [[ $option_resolve == 'yes' && $option_relative == 'yes' && $option_validate == 'no' ]]; then
- if [[ -L $path ]]; then
- "$fallback_readlink" "$path"
+ if is-symlink --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ __sudo -- "$fallback_readlink" "$path"
else
return 45 # ENOTSUP 45 Operation not supported
fi
elif [[ $option_resolve == 'yes' && $option_relative == 'no' && $option_validate == 'yes' ]]; then
# readlink will return correct output when valid
# if invalid, will output nothing and have a failure exit code
- "$fallback_readlink" -f "$path"
+ __sudo -- "$fallback_readlink" -f "$path"
else
return 45 # ENOTSUP 45 Operation not supported
fi
@@ -274,7 +290,7 @@ function fs_realpath() (
if [[ $option_resolve == 'yes' && $option_relative == 'no' && $option_validate == 'yes' ]]; then
# realpath will return correct output when valid
# if invalid, will output error (unless -q) and have failure exit code
- "$fallback_realpath" "$path"
+ __sudo -- "$fallback_realpath" "$path"
else
return 45 # ENOTSUP 45 Operation not supported
fi
@@ -311,9 +327,9 @@ function fs_realpath() (
if [[ $option_relative == 'no' && $option_validate == 'no' ]]; then
if [[ $option_resolve == 'no' ]]; then
- fish -c 'builtin realpath --no-symlinks "$argv[1]"' -- "$path"
+ __sudo -- fish -c 'builtin realpath --no-symlinks "$argv[1]"' -- "$path"
else
- fish -c 'builtin realpath "$argv[1]"' -- "$path"
+ __sudo -- fish -c 'builtin realpath "$argv[1]"' -- "$path"
fi
else
return 45 # ENOTSUP 45 Operation not supported
diff --git a/commands/fs-rm b/commands/fs-rm
index d8acfd5ca..9579a661c 100755
--- a/commands/fs-rm
+++ b/commands/fs-rm
@@ -41,7 +41,7 @@ function fs_rm() (
}
# process
- local item option_quiet='no' option_paths=() option_optional='no' option_confirm='yes' option_sudo='no' option_trash='no' option_user='' option_group=''
+ local item option_quiet='no' option_paths=() option_optional='no' option_confirm='yes' option_sudo='no' option_trash='' option_user='' option_group=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -90,141 +90,152 @@ function fs_rm() (
# =====================================
# Dependencies
- if [[ $option_trash == 'yes' ]]; then
+ local trash_and_delete_options=() trash_or_delete_default
+ if [[ $option_trash == 'yes' || ( -z $option_trash && $option_confirm != 'no' ) ]]; then
setup-util-trash --quiet --optional --no-fallback
- if __command_missing -- trash; then
+ fi
+ if __command_missing -- trash; then
+ if [[ $option_trash = 'yes' ]]; then
echo-style --dim='Moving to trash is not available, falling back to immediate deletion for: ' --code="${option_paths[*]}" >/dev/stderr
- option_trash='no'
fi
+ option_trash='no'
+ trash_and_delete_options+=(
+ delete 'Delete it'
+ )
+ else
+ trash_and_delete_options+=(
+ trash 'Move it to trash'
+ delete 'Delete it'
+ )
+ fi
+ if [[ $option_trash = 'yes' ]]; then
+ trash_or_delete_default='trash'
+ elif [[ $option_trash = 'no' ]]; then
+ trash_or_delete_default='delete'
+ else
+ trash_or_delete_default=$'trash\ndelete'
fi
# =====================================
# Action
- function eval_wrapper {
- while [[ $1 == '--' ]]; do
- shift
- done
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- sudo-helper --no-wrap="$option_quiet" --quiet="$option_quiet" --inherit --user="$option_user" --group="$option_group" \
- -- "$@"
- else
- eval-helper --no-wrap="$option_quiet" --quiet="$option_quiet" \
- -- "$@"
- fi
- }
-
- function do_confirm_trim {
- local path="$1"
-
- # if not a directory, we don't want to trim
- if is-not-directory --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
- return 200 # ECUSTOM 200 Not applicable
- fi
-
- # if preconfirmed, skip the prompt
- if [[ $option_confirm == 'no' ]]; then
- return 0
- fi
-
- # if it is purely empty, skip the prompt
- if is-empty-ls --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
- return 0
- fi
-
- # note its structure and size
- eval_wrapper -- ls -la "$path"
-
- # confirm removal
- confirm --positive --ppid=$$ -- "$(
- echo-style --notice='Trim empty directories?' --bold=" $path " --notice="?"
- )"
+ function __wrap {
+ sudo-helper --no-wrap="$option_quiet" --quiet="$option_quiet" --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$@"
}
- function do_confirm_removal {
- local path="$1"
-
- # if preconfirmed, skip the prompt
- if [[ $option_confirm == 'no' ]]; then
- return 0
- fi
-
- # we want to prompt
- eval_wrapper -- ls -la "$path"
-
- # is a directory, so output extra information
- if [[ -d $path ]]; then
- if __command_exists -- dust; then
- eval_wrapper -- dust --no-percent-bars "$path"
- eval_wrapper -- dust --no-percent-bars --filecount "$path"
- elif __command_exists -- du; then
- eval_wrapper -- du -ahd1 "$path"
- fi
+ function __rm {
+ if [[ $option_trash == 'yes' ]]; then
+ __wrap trash "$path" || :
+ else
+ __wrap rm -rf "$path" || :
fi
-
- # confirm removal
- confirm --positive --ppid=$$ -- "$(
- echo-style --warning='Confirm removal of non-empty' --bold=" $path " --warning="?"
- )"
}
- local CONCLUSION=''
+ local CONCLUSION
function do_rm {
- local path="$1" confirm_trim_status confirm_removal_status
+ local path="$1" title='' body choice
- # is the path missing
+ # is the path already removed?
if is-missing --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
CONCLUSION="$(
- echo-style --green="was previously removed."
+ echo-style --green='was previously removed.'
)"
return 0
fi
- # path exists
- # delete empty directories
- eval_capture --statusvar=confirm_trim_status -- do_confirm_trim "$path"
- if [[ $confirm_trim_status -eq 0 ]]; then
- # ignore stderr and do not wrap to prevent illogical cannot restore directory errors
- eval_capture --ignore-stderr -- eval_wrapper -- find "$path" -empty -type d -delete
- if is-missing --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ # it is remaining, so prompt on what to do
+ choice='trim'
+ while :; do
+ # is the path is empty or a broken symlink, skip any confirm and remove it
+ if is-not-symlink --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ if is-empty-file --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path" || is-empty-directory --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ __rm "$path"
+ if is-present --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ CONCLUSION="$(
+ echo-style --red='is empty, however it failed to remove.'
+ )"
+ return 66 # ENOTEMPTY 66 Directory not empty
+ fi
+ CONCLUSION="$(
+ echo-style --green='was empty, it was removed.'
+ )"
+ return 0
+ fi
+ elif is-broken-symlink --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ __rm "$path"
+ if is-present --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ CONCLUSION="$(
+ echo-style --red='is a broken-symlink, however it failed to remove.'
+ )"
+ return 66 # ENOTEMPTY 66 Directory not empty
+ fi
CONCLUSION="$(
- echo-style --green="was only empty directories, it has been removed."
+ echo-style --green='was a broken-symlink, it was removed.'
)"
return 0
fi
- fi
- # there are leftovers
- # confirm and remove, or no confirm and remove
- eval_capture --statusvar=confirm_removal_status -- do_confirm_removal "$path"
- if [[ $confirm_removal_status -eq 0 ]]; then
- if [[ $option_trash == 'yes' ]]; then
- eval_capture -- eval_wrapper -- trash "$path"
- elif [[ $option_quiet == 'yes' ]]; then
- eval_capture -- eval_wrapper -- rm -rf "$path"
- else
- eval_capture -- eval_wrapper -- rm -rfv "$path"
+ # construct body
+ if [[ -z $title ]]; then
+ title="$(
+ echo-style --notice1='The path is non-empty and queued for removal, what should be done?' --newline \
+ --code-notice1="$path"
+ )"
fi
- fi
- # detect successful removal
+ # refresh body
+ body="$(echo-style --reset)$(fs-structure --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path")"
+
+ # confirm
+ if [[ $option_confirm != 'no' ]]; then
+ choice="$(
+ choose "$title" "$body" --defaults-exact="$choice" --label -- \
+ trim 'Trim its redundant content and re-evaluate' \
+ "${trash_and_delete_options[@]}" \
+ abort 'Keep it, and abort the requested removal'
+ )"
+ fi
+
+ # handle
+ if [[ $choice = 'trim' ]]; then
+ fs-trim --confirm="$option_confirm" --no-all="$option_confirm" --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"
+ if is-missing --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
+ CONCLUSION="$(
+ echo-style --green='was removed by trimming.'
+ )"
+ return 0
+ fi
+ choice="$trash_or_delete_default"
+ elif [[ $choice = 'abort' || -z $choice ]]; then
+ CONCLUSION="$(
+ echo-style --yellow='was kept.'
+ )"
+ return 66 # ENOTEMPTY 66 Directory not empty
+ elif [[ $choice == 'trash' ]]; then
+ __wrap trash "$path" || :
+ break
+ elif [[ $choice == 'delete' ]]; then
+ __wrap rm -rf "$path" || :
+ break
+ fi
+ done
+
+ # check after trash/delete
if is-present --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
CONCLUSION="$(
- echo-style --red="is non-empty, it has been kept."
+ echo-style --red='is non-empty, it failed to remove.'
)"
return 66 # ENOTEMPTY 66 Directory not empty
fi
-
- # success if removed
CONCLUSION="$(
- echo-style --green="was non-empty, it was manually removed."
+ echo-style --green='was non-empty, it was manually removed.'
)"
+ return 0
}
function act {
local path="$1" title rm_status
- if is-present --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path"; then
- path="$(fs-absolute --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$path")"
- fi
+ path="$(fs-absolute -- "$path")"
+ CONCLUSION=''
if [[ $option_quiet == 'yes' ]]; then
do_rm "$path"
return
@@ -236,13 +247,13 @@ function fs_rm() (
if [[ $option_sudo == 'yes' ]]; then
title+=' --sudo'
fi
- if [[ $option_user == 'yes' ]]; then
+ if [[ -n $option_user ]]; then
title+=" --user=$option_user"
fi
- if [[ $option_group == 'yes' ]]; then
+ if [[ -n $option_group ]]; then
title+=" --group=$option_group"
fi
- title+=" $path"
+ title+=" $(echo-escape-command -- "$path")"
echo-style --h2="$title"
eval_capture --statusvar=rm_status -- do_rm "$path"
if [[ $rm_status -eq 0 ]]; then
diff --git a/commands/fs-size b/commands/fs-size
deleted file mode 100755
index fd6b0111a..000000000
--- a/commands/fs-size
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env bash
-
-function fs_size() (
- source "$DOROTHY/sources/bash.bash"
-
- # =====================================
- # Arguments
-
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Output detailed size information about a path.
-
- USAGE:
- fs-size [...options] [--] ...
-
- OPTIONS:
- --quiet
- If not provided, size details are wrapped in more information.
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process
- local item option_quiet='no' option_paths=()
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- '--no-verbose'* | '--verbose'*)
- option_quiet="$(get-flag-value --non-affirmative --fallback="$option_quiet" -- "$item")"
- ;;
- '--no-quiet'* | '--quiet'*)
- option_quiet="$(get-flag-value --affirmative --fallback="$option_quiet" -- "$item")"
- ;;
- '--path='*) option_paths+=("${item#*=}") ;;
- '--')
- option_paths+=("$@")
- shift $#
- break
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_paths+=("$item") ;;
- esac
- done
-
- # check
- if [[ ${#option_paths[@]} -eq 0 ]]; then
- help 'No s provided.'
- fi
-
- # =====================================
- # Dependencies
-
- setup-util-dust --quiet
-
- # =====================================
- # Action
-
- local CONCLUSION=''
- function do_size {
- local path="$1"
-
- # is the path missing
- if is-missing -- "$path"; then
- CONCLUSION='is missing.'
- return 2 # ENOENT 2 No such file or directory
- fi
-
- # note its contents
- __print_line
- eval-helper --no-quiet --wrap \
- -- ls -la "$path"
- __print_line
- if [[ -d $path ]]; then
- eval-helper --no-quiet --wrap \
- -- dust --no-percent-bars "$path"
- __print_line
- eval-helper --no-quiet --wrap \
- -- dust --no-percent-bars --filecount "$path"
- __print_line
- fi
-
- # note the conclusion
- if is-empty-ls -- "$path"; then
- CONCLUSION='is an empty directory.'
- else
- CONCLUSION='is a non-empty directory.'
- fi
- }
-
- function act {
- local path="$1" title size_status
- if [[ $option_quiet == 'yes' ]]; then
- do_size "$path"
- return
- else
- title="fs-size $(echo-escape-command -- "$path")"
- echo-style --h2="$title"
- eval_capture --statusvar=size_status -- do_size "$path"
- if [[ $size_status -eq 0 ]]; then
- echo-style --g2="$title" " $CONCLUSION"
- else
- echo-style --e2="$title" " $CONCLUSION"
- return "$size_status"
- fi
- fi
- }
-
- local path
- for path in "${option_paths[@]}"; do
- act "$path"
- done
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- fs_size "$@"
-fi
diff --git a/commands/fs-structure b/commands/fs-structure
index f539a149e..d0a91a889 100755
--- a/commands/fs-structure
+++ b/commands/fs-structure
@@ -15,8 +15,21 @@ function fs_structure() (
fs-structure [...options] [--] ...
OPTIONS:
+ --no-perms
+ If specified, don't display permission and ownerships information.
+ Only applicable when [eza] is used.
+ --no-time
+ If specified, don't display time information.
+ --no-eza
+ If specified, don't try to use [eza].
+ --no-color
+ If specified, don't use colors.
+
--sudo
- If specified, use sudo when removing the files.
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -25,7 +38,8 @@ function fs_structure() (
}
# process
- local item option_paths=() option_sudo='no'
+ local item option_inputs=() option_sudo='no' option_user='' option_group='' option_perms='' option_time='' option_eza='' option_color
+ option_color="$(get-terminal-color-support --fallback=yes -- "$@")"
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -34,59 +48,141 @@ function fs_structure() (
'--no-sudo'* | '--sudo'*)
option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
;;
- '--path='*) paths+=("${item#*=}") ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--no-perms'* | '--perms'* | '--no-permissions'* | '--permissions'*)
+ option_perms="$(get-flag-value --affirmative --fallback="$option_perms" -- "$item")"
+ ;;
+ '--no-time'* | '--time'*)
+ option_time="$(get-flag-value --affirmative --fallback="$option_time" -- "$item")"
+ ;;
+ '--no-eza'* | '--eza'*)
+ option_eza="$(get-flag-value --affirmative --fallback="$option_eza" -- "$item")"
+ ;;
+ '--no-color'* | '--color'*) : ;; # handled by get-terminal-color-support
'--')
- option_paths+=("$@")
+ option_inputs+=("$@")
shift $#
break
;;
'--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_paths+=("$item") ;;
+ *) option_inputs+=("$item") ;;
esac
done
# check
- if [[ ${#option_paths[@]} -eq 0 ]]; then
- help 'No s provided.'
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ option_inputs+=('.')
fi
# =====================================
# Action
- # prepare
- local cmd=()
- if [[ $option_sudo == 'yes' ]]; then
- cmd+=(
- 'sudo-helper'
- '--'
- )
+ # dependencies
+ if [[ $option_eza != 'no' ]]; then
+ setup-util-eza --quiet --optional
fi
- cmd+=(
- 'ls'
- '-lA'
- )
- # -A, --almost-all: do not list implied . and ..
- # -l: use a long listing format
+ # another alternative is lsd:
+ # lsd -lA --total-size --header
+ # however it doesn't support removing time, and removing owner/permissions
+
+ # prepare
+ local eza_cmd=() ls_cmd=() # dust_sizes_cmd=() dust_counts_cmd=() du_cmd=()
+ if [[ $option_eza != 'no' ]] && __command_exists -- eza; then
+ # -h, --header: Add a header row to each column.
+ # -l, --long: Display extended file metadata as a table.
+ # -A, --almost-all: Equivalent to –all; included for compatibility with ls -A.
+ # -M, --mounts: how mount details (Linux and Mac only)
+ # --total-size: show the size of a directory as the size of all files and directories inside (unix only)
+ eza_cmd+=(eza -hlAM --total-size)
+
+ # hide the permissions?
+ if [[ $option_perms == 'no' ]]; then
+ eza_cmd+=(--no-permissions --no-user)
+ fi
+
+ # hide the time?
+ if [[ $option_time == 'no' ]]; then
+ eza_cmd+=(--no-time)
+ fi
- # hide the time
- if is-mac; then
- # -D format: When printing in the long (-l) format, use format to format the date and time output. The argument format is a string used by trftime(3). Depending on the choice of format string, this may result in a different number of columns in the output. This option overrides the -T option. This option is not defined in IEEE Std 1003.1-2008 (“POSIX.1”).
- cmd+=('-D' '')
+ # disable colors?
+ if [[ $option_color == 'no' ]]; then
+ eza_cmd+=('--color=never')
+ elif [[ $option_color == 'yes' ]]; then
+ eza_cmd+=('--color=always')
+ fi
else
- # --time-style=TIME_STYLE: time/date format with -l; see TIME_STYLE below
- cmd+=("--time-style=+''")
+ # -A, --almost-all: do not list implied . and ..
+ # -l: use a long listing format
+ # -h: When used with the -l option, use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the number of digits to four or fewer using base 2 for sizes. This option is not defined in IEEE Std 1003.1-2008 (“POSIX.1”).
+ ls_cmd+=(ls -lAh)
+
+ # hide the time?
+ if [[ $option_time == 'no' ]]; then
+ if is-mac; then
+ # -D format: When printing in the long (-l) format, use format to format the date and time output. The argument format is a string used by trftime(3). Depending on the choice of format string, this may result in a different number of columns in the output. This option overrides the -T option. This option is not defined in IEEE Std 1003.1-2008 (“POSIX.1”).
+ ls_cmd+=('-D' '')
+ else
+ # --time-style=TIME_STYLE: time/date format with -l; see TIME_STYLE below
+ ls_cmd+=("--time-style=+''")
+ fi
+ fi
+
+ # counts
+ # if __command_exists -- dust; then
+ # dust_sizes_cmd+=(dust --no-percent-bars)
+ # dust_counts_cmd+=(dust --no-percent-bars --filecount)
+ # elif __command_exists -- du; then
+ # du_cmd+=(du -hd1)
+ # fi
+
+ # disable colors?
+ if [[ $option_color == 'no' ]]; then
+ ls_cmd+=('--color=never')
+ # dust_sizes_cmd+=('--no-colors')
+ # dust_counts_cmd+=('--no-colors')
+ elif [[ $option_color == 'yes' ]]; then
+ ls_cmd+=('--color=always')
+ # dust_sizes_cmd+=('--force-colors')
+ # dust_counts_cmd+=('--force-colors')
+ fi
fi
- local path
- for path in "${option_paths[@]}"; do
+ # helpers
+ function __wrap {
+ sudo-helper --inherit --no-wrap --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$@"
+ }
+ function __act() (
+ # subshell to prevent multiple cds conflicting with each other
+ local path="$1" basename
if [[ -d $path ]]; then
cd "$path"
- "${cmd[@]}"
+ basename='.'
else
cd "$(dirname "$path")"
basename="$(basename "$path")"
- "${cmd[@]}" "$basename" | sd --fixed-strings "$basename" ''
fi
+ if [[ ${#eza_cmd[@]} -ne 0 ]]; then
+ __wrap "${eza_cmd[@]}" "$basename"
+ fi
+ if [[ ${#ls_cmd[@]} -ne 0 ]]; then
+ __wrap "${ls_cmd[@]}" "$basename"
+ fi
+ # if [[ ${#dust_sizes_cmd[@]} -ne 0 ]]; then
+ # __wrap "${dust_sizes_cmd[@]}" "$basename"
+ # fi
+ # if [[ ${#dust_counts_cmd[@]} -ne 0 ]]; then
+ # __wrap "${dust_counts_cmd[@]}" "$basename"
+ # fi
+ # if [[ ${#du_cmd[@]} -ne 0 ]]; then
+ # __wrap "${du_cmd[@]}" "$basename"
+ # fi
+ )
+
+ local input
+ for input in "${option_inputs[@]}"; do
+ __act "$input"
done
)
diff --git a/commands/fs-temp b/commands/fs-temp
index 001c51a66..44ff09b8b 100755
--- a/commands/fs-temp
+++ b/commands/fs-temp
@@ -44,7 +44,8 @@ function fs_temp() (
When generating a , use this .
--touch
- If a was provided, then touch the file to ensure it exists.
+ Unless falsey, then directories will be made.
+ If truthy, the file, if applicable, will be created.
QUIRKS:
Unless [--touch] is truthy, then file paths won't be created on the file system.
@@ -67,7 +68,7 @@ function fs_temp() (
local option_prefix=''
local option_suffix=''
local option_extension=''
- local option_touch='no'
+ local option_touch=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -134,7 +135,9 @@ function fs_temp() (
done
# ensure the root now exists
- __mkdirp "$root"
+ if [[ $option_touch != 'no' ]]; then
+ __mkdirp "$root"
+ fi
# if no files, output directory path
if [[ ${#option_files[@]} -eq 0 ]]; then
diff --git a/commands/fs-trim b/commands/fs-trim
new file mode 100755
index 000000000..6ab2f727a
--- /dev/null
+++ b/commands/fs-trim
@@ -0,0 +1,347 @@
+#!/usr/bin/env bash
+
+function fs_trim_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- fs-trim --
+
+ eval-tester --name='empty args' --status=22 \
+ -- fs-trim -- '' ''
+
+ eval-tester --name='missing' \
+ -- fs-trim -- "$DOROTHY/this-doesnt-exist"
+
+ # test working symlinks
+ local root dir_target dir_symlink file_in_dir_target file_target file_symlink file_in_dir_symlink
+ root="$(fs-temp --directory='fs-trim' --touch)"
+ dir_target="$(fs-temp --root="$root" --directory='dir_target' --touch)"
+ file_target="$(fs-temp --root="$root" --file='file_target' --touch)"
+ file_in_dir_target="$(fs-temp --root="$dir_target" --file='file_in_dir_target' --touch)"
+ dir_symlink="$(fs-temp --root="$root" --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --root="$root" --file='file_symlink' --no-touch)"
+ file_in_dir_symlink="$(fs-temp --root="$dir_target" --file='file_in_dir_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+ symlink-helper --existing="$file_in_dir_target" --symlink="$file_in_dir_symlink" --quiet
+
+ # add data and test no-op trim
+ __print_line 'sup' >"$file_in_dir_target"
+ eval-tester --name='trim non-empty dir target should be no-op' \
+ -- fs-trim -- "$dir_target"
+ eval-tester --name='trim non-empty dir symlink should be no-op' \
+ -- fs-trim -- "$dir_symlink"
+ eval-tester --name='trim non-empty dir should be no-op (check)' \
+ -- is-present -- "$root" "$dir_target" "$file_target" "$file_in_dir_target" "$dir_symlink" "$file_symlink" "$file_in_dir_symlink"
+
+ # test symlinks
+ eval-tester --name='trim file symlink should remove its empty target and itself' \
+ -- fs-trim -- "$file_symlink"
+ eval-tester --name='trim file symlink should remove its empty target and itself (check)' \
+ -- is-missing -- "$file_target" "$file_symlink"
+
+ # make it empty and test again
+ printf '' >"$file_in_dir_target"
+ eval-tester --name='trim root without --all should be no-op' \
+ -- fs-trim -- "$root"
+ eval-tester --name='trim root without --all should be no-op (check)' \
+ -- is-present -- "$root" "$dir_target" "$file_in_dir_target" "$dir_symlink" "$file_in_dir_symlink"
+ eval-tester --name='trim root with --all should trim everything' \
+ -- fs-trim --all -- "$root"
+ eval-tester --name='trim root with --all should trim everything (check)' \
+ -- is-missing -- "$root"
+
+ # recreate empty dirs and files
+ dir_target="$(fs-temp --root="$root" --directory='dir_target' --touch)"
+ file_target="$(fs-temp --root="$root" --file='file_target' --touch)"
+ file_in_dir_target="$(fs-temp --root="$dir_target" --file='file_in_dir_target' --touch)"
+ eval-tester --name='trim root that has empty files and empty dirs, with --empty-files, should trim everything' \
+ -- fs-trim --empty-files -- "$root"
+ eval-tester --name='trim root that has empty files and empty dirs, with --empty-files, should trim everything (check)' \
+ -- is-missing -- "$root"
+
+ # recreate empty dirs
+ dir_target="$(fs-temp --root="$root" --directory='dir_target' --touch)"
+ eval-tester --name='trim root that has only empty dirs, should trim everything' \
+ -- fs-trim -- "$root"
+ eval-tester --name='trim root that has only empty dirs, should trim everything (check)' \
+ -- is-missing -- "$root"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function fs_trim() (
+ source "$DOROTHY/sources/bash.bash"
+ local junk_filenames=(
+ '.DS_Store'
+ '._.DS_Store'
+ 'Desktop.ini'
+ 'Thumbs.db'
+ 'node_modules'
+ 'pnp'
+ 'package-lock.json'
+ 'yarn.lock'
+ '.pnp.js'
+ '.log'
+ )
+ local junk_find=() remove_filenames=() item
+ for item in "${junk_filenames[@]}"; do
+ item="$(__lowercase_string -- "$item")"
+ remove_filenames+=("$item")
+ junk_find+=(-iname "$item" -or)
+ done
+ junk_find=("${junk_find[@]:0:${#junk_find[@]}-1}")
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Trim s of empty files and directories, including itself it also became empty.
+
+ USAGE:
+ fs-trim [...options] [--] ...
+
+ OPTIONS:
+ --quiet | --no-verbose
+ If specified, do not confirm for action if none provided.
+ --confirm
+ If specified, confirm for action if none provided.
+
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ --junk
+ If provided, paths of these case-insensitive filenames will be removed: ${junk_filenames[*]}
+ --empty-files
+ If provided, empty files will be removed.
+ --broken-symlinks
+ If provided, broken symlinks will be removed.
+ --empty-directories
+ If provided, empty directories will be removed.
+
+ RETURNS:
+ [0] if all s were trimmed of empty files/directories
+ [22] if empty arguments are provided
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group='' option_confirm='' option_all='' option_junk='' option_empty_files='' option_broken_symlinks='' option_empty_directories=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--no-confirm'* | '--confirm'*)
+ option_confirm="$(get-flag-value --affirmative --fallback="$option_confirm" -- "$item")"
+ ;;
+ '--no-all'* | '--all'*)
+ option_all="$(get-flag-value --affirmative --fallback="$option_all" -- "$item")"
+ if [[ $option_all == 'yes' ]]; then
+ option_junk='yes'
+ option_empty_files='yes'
+ option_broken_symlinks='yes'
+ option_empty_directories='yes'
+ fi
+ ;;
+ '--no-junk'* | '--junk'*)
+ option_junk="$(get-flag-value --affirmative --fallback="$option_junk" -- "$item")"
+ ;;
+ '--no-empty-files'* | '--empty-files'*)
+ option_empty_files="$(get-flag-value --affirmative --fallback="$option_empty_files" -- "$item")"
+ ;;
+ '--no-broken-symlinks'* | '--broken-symlinks'*)
+ option_broken_symlinks="$(get-flag-value --affirmative --fallback="$option_broken_symlinks" -- "$item")"
+ ;;
+ '--no-empty-directories'* | '--empty-directories'*)
+ option_empty_directories="$(get-flag-value --affirmative --fallback="$option_empty_directories" -- "$item")"
+ ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ option_inputs+=("$(pwd)")
+ fi
+
+ # =====================================
+ # Action
+
+ local selection=()
+ if [[ $option_junk == 'yes' ]]; then
+ selection+=('junk')
+ fi
+ if [[ $option_empty_files == 'yes' ]]; then
+ selection+=('files')
+ fi
+ if [[ $option_broken_symlinks == 'yes' ]]; then
+ selection+=('broken')
+ fi
+ if [[ $option_empty_directories == 'yes' ]]; then
+ selection+=('directories')
+ fi
+ if [[ ${#selection[@]} -eq 0 ]]; then
+ selection+=('directories')
+ option_confirm='yes'
+ fi
+
+ # helpers
+ local confirmed='no'
+ function __confirm {
+ local title
+ if [[ $confirmed = 'yes' ]]; then
+ return 0
+ fi
+ confirmed='yes'
+ if [[ $option_confirm = 'yes' ]]; then
+ title="$(
+ echo-style --notice1='What items do you wish to trim for:' --newline \
+ --code-notice1="$(fs-absolute -- "${option_inputs[@]}")"
+ )"
+ mapfile -t selection < <(
+ choose "$title" --multiple --defaults-exact="$(__print_lines "${selection[@]}")" --label -- \
+ junk "Junk files: $(echo-style --newline --dim="${junk_filenames[*]}")" \
+ files 'Empty files' \
+ broken 'Broken symlinks' \
+ directories 'Empty directories'
+ )
+ fi
+ # still apply defaults in no-confirm mode
+ for item in "${selection[@]}"; do
+ case "$item" in
+ 'junk') option_junk='yes' ;;
+ 'files') option_empty_files='yes' ;;
+ 'broken') option_broken_symlinks='yes' ;;
+ 'directories') option_empty_directories='yes' ;;
+ esac
+ done
+ }
+ function __wrap {
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$@"
+ }
+ function do_find {
+ local path="$1" refresh='yes'
+ while [[ $refresh = 'yes' ]]; do
+ refresh='no'
+ if is-not-directory --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ break
+ fi
+ if [[ $option_junk == 'yes' ]] && __wrap find "$path" \( "${junk_find[@]}" \) -delete -print | ifne -n false >/dev/null; then
+ refresh='yes'
+ fi
+ if [[ $option_empty_files == 'yes' ]] && __wrap find "$path" -type f -empty -delete -print | ifne -n false >/dev/null; then
+ refresh='yes'
+ fi
+ if [[ $option_broken_symlinks == 'yes' ]] && __wrap find "$path" -type l -exec fs-trim-symlinks.bash -- {} + | ifne -n false >/dev/null; then
+ refresh='yes'
+ fi
+ if [[ $option_empty_directories == 'yes' ]] && __wrap find "$path" -type d -empty -delete -print | ifne -n false >/dev/null; then
+ refresh='yes'
+ fi
+ done
+ }
+
+ # action
+ local input target input_lowercase_filename target_lowercase_filename
+ for input in "${option_inputs[@]}"; do
+ # check is invalid
+ if [[ -z $input ]]; then
+ return 22 # EINVAL 22 Invalid argument
+ fi
+ # just -e is faulty, as -e fails on broken symlinks
+ if is-missing --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ # already missing on the filesystem
+ continue
+ fi
+ # confirm the user for action if still ambiguous
+ __confirm
+ # check we have something to do
+ if [[ $option_junk != 'yes' && $option_empty_files != 'yes' && $option_broken_symlinks != 'yes' && $option_empty_directories != 'yes' ]]; then
+ # no-op, user is aborting essentially
+ return 0
+ fi
+ # continue
+ if is-symlink --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ # it is a symlink
+ if is-broken-symlink --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ # it is broken, remove it if desired
+ if [[ $option_broken_symlinks == 'yes' ]]; then
+ __wrap rm -f "$input"
+ fi
+ continue
+ fi
+
+ # get the target
+ target="$(fs-realpath -- "$input")"
+
+ # check if it is a junk file
+ if [[ $option_junk == 'yes' ]]; then
+ target_lowercase_filename="$(__lowercase_string -- "$(fs-filename -- "$target")")"
+ input_lowercase_filename="$(__lowercase_string -- "$(fs-filename -- "$input")")"
+ if is-needle --needle="$input_lowercase_filename" -- "${remove_filenames[@]}" || is-needle --needle="$target_lowercase_filename" -- "${remove_filenames[@]}"; then
+ __wrap rm -f "$target" "$input"
+ continue
+ fi
+ fi
+
+ # trim target and symlink
+ if is-directory --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$target"; then
+ # it is a directory or symlink to a directory on the filesystem
+ do_find "$target"
+ # remove the symlink if its target was just removed
+ if is-missing --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$target"; then
+ __wrap rm -f "$input"
+ fi
+ elif [[ $option_empty_files == 'yes' ]] && is-empty-file --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$target"; then
+ __wrap rm -f "$target" "$input"
+ fi
+ else
+ # check if it is a junk file
+ if [[ $option_junk == 'yes' ]]; then
+ input_lowercase_filename="$(__lowercase_string -- "$(fs-filename -- "$input")")"
+ if is-needle --needle="$input_lowercase_filename" -- "${remove_filenames[@]}"; then
+ __wrap rm -f "$input"
+ continue
+ fi
+ fi
+
+ # trim input target
+ if is-directory --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ # it is a directory or symlink to a directory on the filesystem
+ do_find "$input"
+ elif [[ $option_empty_files == 'yes' ]] && is-empty-file --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- "$input"; then
+ __wrap rm -f "$input"
+ fi
+ fi
+ done
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ fs_trim_test
+ else
+ fs_trim "$@"
+ fi
+fi
diff --git a/commands/fs-trim-symlinks.bash b/commands/fs-trim-symlinks.bash
new file mode 100755
index 000000000..e8b278430
--- /dev/null
+++ b/commands/fs-trim-symlinks.bash
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+remove=()
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ -L $1 && ! -e $1 ]]; then
+ remove+=("$1")
+ fi
+ shift
+done
+if [[ ${#remove[@]} -ne 0 ]]; then
+ rm -fv "${remove[@]}"
+fi
+exit 0
diff --git a/commands/get-terminal-color-support b/commands/get-terminal-color-support
index 552aae7d2..3d38f4ae9 100755
--- a/commands/get-terminal-color-support
+++ b/commands/get-terminal-color-support
@@ -30,9 +30,14 @@ function get_terminal_color_support() (
Checks for [--[no-]color[s]=[yes|no]] arguments, as well as [[NO[_]]COLOR] and [CRON], [CRONITOR_EXEC], and [TERM] environment variables.
RETURNS:
+ If in quiet mode:
[0] if enabled
[1] if disabled
[91] if not determined (no fallback).
+
+ If not in quiet mode:
+ [0] if enabled or disabled
+ [91] if not determined (no fallback).
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/get-terminal-theme b/commands/get-terminal-theme
index 298dd875e..10f3c9b02 100755
--- a/commands/get-terminal-theme
+++ b/commands/get-terminal-theme
@@ -114,7 +114,7 @@ function get_terminal_theme() (
local bg="$COLORFGBG"
if [[ -n $bg ]]; then
bg="${bg##*;}" # trim everything prior to the last ;
- if [[ $bg == 'default' ]] || (is-digit -- "$bg" && [[ $bg -le 6 || $bg -eq 8 ]]); then
+ if [[ $bg == 'default' ]] || (is-integer -- "$bg" && [[ $bg -le 6 || $bg -eq 8 ]]); then
theme='light'
else
theme='dark'
diff --git a/commands/gocryptfs-helper b/commands/gocryptfs-helper
index e187a2782..cad1fea22 100755
--- a/commands/gocryptfs-helper
+++ b/commands/gocryptfs-helper
@@ -282,7 +282,7 @@ function gocryptfs_helper() (
)"
# create
- if is-missing -- "$new_vault" || is-empty-ls -- "$new_vault"; then
+ if is-missing -- "$new_vault" || is-empty-directory -- "$new_vault"; then
__mkdirp "$new_vault"
echo-style --bold="Creating a new vault vault at [$new_vault] with algorithm [$algorithm]."
gocryptfs --init --"$algorithm" "$new_vault"
@@ -337,7 +337,7 @@ function gocryptfs_helper() (
echo-style --notice="The new vault [$new_vault] already exists..." --newline \
'This means a vault upgrade was started but not finished.' --newline \
'We will continue with this vault, if you wish setup a new one, remove the old one first.'
- elif is-missing -- "$new_vault" || is-empty-ls -- "$new_vault"; then
+ elif is-missing -- "$new_vault" || is-empty-directory -- "$new_vault"; then
echo-style --bold="Creating a new vault vault at [$new_vault] with algorithm [$algorithm]."
gocryptfs --init --"$algorithm" "$new_vault"
act_chown "$new_vault"
@@ -371,11 +371,11 @@ function gocryptfs_helper() (
# replace
__print_lines '' 'Prepping replacement:'
fs-rm --no-confirm -- "$old_plain/"
- fs-size -- "$new_plain/"
+ fs-structure -- "$new_plain/"
mount-helper \
-- --unmount --target="$old_plain" \
-- --unmount --target="$new_plain"
- fs-size -- "$old_vault" "$new_vault"
+ fs-structure -- "$old_vault" "$new_vault"
# @todo style with var_dump or something
echo-style --bold='Confirm the following replacement:' --newline \
--bold+red='Delete:' ' ' --code="$old_vault" --newline \
diff --git a/commands/is-abort b/commands/is-abort
index 3de8812cb..b360edbde 100755
--- a/commands/is-abort
+++ b/commands/is-abort
@@ -28,8 +28,8 @@ function is_abort() (
143: SIGTERM (Termination signal. Sent to request a process to terminate gracefully.)
RETURNS:
- [0] if ANY s were an abort
- [1] if ALL were not abort
+ [0] if ANY s are an abort
+ [1] if all s are not abort
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-admin b/commands/is-admin
index 4da4c8562..dd256804a 100755
--- a/commands/is-admin
+++ b/commands/is-admin
@@ -20,8 +20,8 @@ function is_admin() (
User to check is an administrator.
RETURNS:
- [0] if all s were an administrator.
- [1] if any s were not an administrator.
+ [0] if all s are an administrator.
+ [1] if any s are not an administrator.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -64,7 +64,7 @@ function is_admin() (
fi
# act
- if is-user-in-group --group="$group" "${option_users[@]}"; then
+ if is-user-in-group --group="$group" -- "${option_users[@]}"; then
return 0
else
return 1
diff --git a/commands/is-affirmative b/commands/is-affirmative
index b88b71499..7aaa50440 100755
--- a/commands/is-affirmative
+++ b/commands/is-affirmative
@@ -22,9 +22,9 @@ function __is_affirmative() (
Ignore/skip empty values.
RETURNS:
- [0] if all s were affirmative
- [1] if any was non-affirmative
- [91] if invalid values were provided, or no s were provided
+ [0] if all s are affirmative
+ [1] if any s are non-affirmative
+ [91] if invalid values are provided, or no s are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@" || return
diff --git a/commands/is-arch b/commands/is-arch
index be0791e21..f05de4af1 100755
--- a/commands/is-arch
+++ b/commands/is-arch
@@ -39,11 +39,8 @@ function is_arch() (
# =====================================
# Action
- if [[ -f '/etc/arch-release' ]]; then
- return 0
- else
- return 1
- fi
+ [[ -f '/etc/arch-release' ]]
+ return
)
# fire if invoked standalone
diff --git a/commands/is-bash-version-outdated b/commands/is-bash-version-outdated
index 6928ea317..acb25308f 100755
--- a/commands/is-bash-version-outdated
+++ b/commands/is-bash-version-outdated
@@ -84,11 +84,8 @@ function is_bash_version_outdated() (
echo-style --bold='latest known bash version' ' = ' --invert="$BASH_VERSION_LATEST"
echo-style --bold='version outdated' ' = ' --invert="$IS_BASH_VERSION_OUTDATED"
fi
- if [[ $IS_BASH_VERSION_OUTDATED == 'yes' ]]; then
- return 0
- else
- return 1
- fi
+ [[ $IS_BASH_VERSION_OUTDATED == 'yes' ]]
+ return
)
# fire if invoked standalone
diff --git a/commands/is-broken-symlink b/commands/is-broken-symlink
new file mode 100755
index 000000000..d8b920486
--- /dev/null
+++ b/commands/is-broken-symlink
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+
+function is_broken_symlink_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-broken-symlink --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-broken-symlink -- '' ''
+
+ eval-tester --name='missing' --status=9 \
+ -- is-broken-symlink -- "$DOROTHY/this-doesnt-exist"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-broken-symlink' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-broken-symlink' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-broken-symlink' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-broken-symlink' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' --status=1 \
+ -- is-broken-symlink -- "$dir_symlink"
+
+ eval-tester --name='symlink file' --status=1 \
+ -- is-broken-symlink -- "$file_symlink"
+
+ eval-tester --name='symlink dir then dir' --status=1 \
+ -- is-broken-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='symlink file then file' --status=1 \
+ -- is-broken-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='symlink file then missing' --status=1 \
+ -- is-broken-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' \
+ -- is-broken-symlink -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' \
+ -- is-broken-symlink -- "$file_symlink"
+
+ eval-tester --name='broken symlink dir then dir' --status=9 \
+ -- is-broken-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='broken symlink file then file' --status=9 \
+ -- is-broken-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='broken symlink file then missing' --status=9 \
+ -- is-broken-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_broken_symlink() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Check if all s are a broken symlink.
+
+ USAGE:
+ is-broken-symlink [...options] [--] ...
+
+ OPTIONS:
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ RETURNS:
+ [0] if all s were a broken symlink
+ [1] if any s were a symlink that was not broken symlink
+ [9] if any s were not a symlink
+ [22] if empty arguments are provided
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided.'
+ fi
+
+ # =====================================
+ # Action
+
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-broken-symlink.bash -- "${option_inputs[@]}"
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_broken_symlink_test
+ else
+ is_broken_symlink "$@"
+ fi
+fi
diff --git a/commands/is-broken-symlink.bash b/commands/is-broken-symlink.bash
new file mode 100755
index 000000000..c5fbc70d1
--- /dev/null
+++ b/commands/is-broken-symlink.bash
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -L $1 ]]; then
+ # not a symlink
+ exit 9 # EBADF 9 Bad file descriptor
+ fi
+ if [[ -e $1 ]]; then
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands/is-digit b/commands/is-digit
index 4e7a2c5cc..3eed85c3f 100755
--- a/commands/is-digit
+++ b/commands/is-digit
@@ -4,7 +4,7 @@ function is_digit_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --name='0-9 ARE a digits' --status=0 \
+ eval-tester --name='0-9 ARE a digits' \
-- is-digit -- 0 1 2 3 4 5 6 7 8 9
eval-tester --name='decimal IS NOT a digit' --status=1 \
@@ -41,7 +41,8 @@ function is_digit() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Checks if the is a single digit (0-9)
+ Checks if the is a single digit (0-9).
+ Companion to [is-number] and [is-integer].
USAGE:
is-digit [...options] [--]
@@ -51,8 +52,8 @@ function is_digit() (
Verify this is a valid digit
RETURNS:
- [0] if all s were valid digits
- [1] if any s were not valid digits
+ [0] if all s are valid digits
+ [1] if any s are not valid digits
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-directory b/commands/is-directory
index ad6c7ddc8..a6914ae39 100755
--- a/commands/is-directory
+++ b/commands/is-directory
@@ -1,5 +1,63 @@
#!/usr/bin/env bash
+function is_directory_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-directory --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-directory -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-directory -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='directory' \
+ -- is-directory -- "$DOROTHY"
+
+ eval-tester --name='file' --status=1 \
+ -- is-directory -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir' --status=1 \
+ -- is-directory -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='dir then file' --status=1 \
+ -- is-directory -- "$DOROTHY" "$DOROTHY/README.md"
+
+ eval-tester --name='dir then file then invalid' --status=1 \
+ -- is-directory -- "$DOROTHY" "$DOROTHY/README.md" ''
+
+ eval-tester --name='dir then invalid then file' --status=22 \
+ -- is-directory -- "$DOROTHY" '' "$DOROTHY/README.md"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-directory' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-directory' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-directory' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-directory' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' \
+ -- is-directory -- "$dir_symlink"
+
+ eval-tester --name='symlink file' --status=1 \
+ -- is-directory -- "$file_symlink"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' --status=1 \
+ -- is-directory -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' --status=1 \
+ -- is-directory -- "$file_symlink"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_directory() (
source "$DOROTHY/sources/bash.bash"
@@ -9,21 +67,23 @@ function is_directory() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Check if all s are a directory (and not a symlink).
+ Check if all s are a file, or an unbroken symlink to a file.
+ Companion to [is-not-directory], [echo-if-directory], [is-empty-directory].
USAGE:
is-directory [...options] [--] ...
OPTIONS:
--sudo
- If specified, use sudo on directorysystem interactions.
+ If specified, use sudo on filesystem interactions.
--user=
--group=
- If specified use this user and/or group for directorysystem interactions.
+ If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were a directory
- [1] if any s were not a directory
+ [0] if all s are a directory, or an unbroken symlink to a directory
+ [1] if any s are neither a directory, nor an unbroken symlink to a directory
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -61,20 +121,15 @@ function is_directory() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-directory.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-directory.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-directory.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_directory "$@"
+ if [[ $* == '--test' ]]; then
+ is_directory_test
+ else
+ is_directory "$@"
+ fi
fi
diff --git a/commands/is-directory.bash b/commands/is-directory.bash
index b582ca94e..ce013d181 100755
--- a/commands/is-directory.bash
+++ b/commands/is-directory.bash
@@ -7,7 +7,12 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
- [[ -d $1 && ! -L $1 ]] || exit
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -d $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-empty-directory b/commands/is-empty-directory
new file mode 100755
index 000000000..c158d4793
--- /dev/null
+++ b/commands/is-empty-directory
@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+
+function is_empty_directory_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ local dir
+ dir="$(fs-temp --directory='is-empty-directory' --directory --touch)"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-empty-directory --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-empty-directory -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-empty-directory -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='empty dir is empty' \
+ -- is-empty-directory -- "$dir"
+
+ eval-tester --name='empty dirs are empty' \
+ -- is-empty-directory -- "$dir" "$dir"
+
+ eval-tester --name='non-empty dir is not empty' --status=1 \
+ -- is-empty-directory -- "$DOROTHY"
+
+ eval-tester --name='file is special failure' --status=20 \
+ -- is-empty-directory -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then non-empty dir is special failure' --status=20 \
+ -- is-empty-directory -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='non-empty dir then file standard failure' --status=1 \
+ -- is-empty-directory -- "$DOROTHY" "$DOROTHY/README.md"
+
+ eval-tester --name='empty then file then non-empty dir is special failure' --status=20 \
+ -- is-empty-directory -- "$dir" "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='empty then non-empty dir then file standard failure' --status=1 \
+ -- is-empty-directory -- "$dir" "$DOROTHY" "$DOROTHY/README.md"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_empty_directory() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Checks if a is an empty directory, aka a directory without any contents.
+
+ USAGE:
+ is-empty-directory [...options] [--] ...
+
+ OPTIONS:
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ RETURNS:
+ [0] if all s are empty
+ [1] if any s are not empty
+ [20] if any s is not a directory.
+ [22] if empty arguments are provided
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift "$#"
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # check
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help "No s provided."
+ fi
+
+ # =====================================
+ # Action
+
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-empty-directory.bash -- "${option_inputs[@]}"
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_empty_directory_test
+ else
+ is_empty_directory "$@"
+ fi
+fi
diff --git a/commands/is-empty-directory.bash b/commands/is-empty-directory.bash
new file mode 100755
index 000000000..b54ebca08
--- /dev/null
+++ b/commands/is-empty-directory.bash
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -d $1 ]]; then
+ exit 20 # ENOTDIR 20 Not a directory
+ fi
+ if [[ -n "$(ls -A "$1")" ]]; then
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands/is-empty-file b/commands/is-empty-file
new file mode 100755
index 000000000..8fd30558e
--- /dev/null
+++ b/commands/is-empty-file
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+
+function is_empty_file_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ local dir file
+ dir="$(fs-temp --directory='is-empty-file' --directory --touch)"
+ file="$(fs-temp --directory='is-empty-file' --file --touch)"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-empty-file --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-empty-file -- '' ''
+
+ eval-tester --name='missing' --status=9 \
+ -- is-empty-file -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='empty dirs' --status=9 \
+ -- is-empty-file -- "$dir" "$dir"
+
+ eval-tester --name='empty files' \
+ -- is-empty-file -- "$file" "$file"
+
+ eval-tester --name='non-empty dir' --status=9 \
+ -- is-empty-file -- "$DOROTHY"
+
+ eval-tester --name='non-empty file' --status=1 \
+ -- is-empty-file -- "$DOROTHY/README.md"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_empty_file() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Checks if a is an empty file, aka a file without content, aka a file with zero-length content.
+
+ USAGE:
+ is-empty-file [...options] [--] ...
+
+ OPTIONS:
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ RETURNS:
+ [0] if all s are empty file
+ [1] if any s are not an empty file.
+ [9] if any s are not a file.
+ [22] if empty arguments are provided.
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift "$#"
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # check
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help "No s provided."
+ fi
+
+ # =====================================
+ # Action
+
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-empty-file.bash -- "${option_inputs[@]}"
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_empty_file_test
+ else
+ is_empty_file "$@"
+ fi
+fi
diff --git a/commands/is-empty-file.bash b/commands/is-empty-file.bash
new file mode 100755
index 000000000..8605ce148
--- /dev/null
+++ b/commands/is-empty-file.bash
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -f $1 ]]; then
+ # not a file nor symlink to a file
+ exit 9 # EBADF 9 Bad file descriptor
+ fi
+ if [[ -s $1 ]]; then
+ # not empty
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands/is-empty-ls b/commands/is-empty-ls
deleted file mode 100755
index b90b0dbc0..000000000
--- a/commands/is-empty-ls
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env bash
-
-function is_empty_ls() (
- source "$DOROTHY/sources/bash.bash"
-
- # =====================================
- # Arguments
-
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Checks if has no contents.
-
- USAGE:
- is-empty-ls [...options] [--] ...
-
- OPTIONS:
- --sudo
- If specified, use sudo on filesystem interactions.
- --user=
- --group=
- If specified use this user and/or group for filesystem interactions.
-
- RETURNS:
- [0] if all s were empty.
- [1] if any s were not empty.
- [2] if any were not a directory.
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process
- local item option_paths=() option_sudo='no' option_user='' option_group=''
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- '--no-sudo'* | '--sudo'*)
- option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
- ;;
- '--user='*) option_user="${item#*=}" ;;
- '--group='*) option_group="${item#*=}" ;;
- '--')
- option_paths+=("$@")
- shift "$#"
- break
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_paths+=("$item") ;;
- esac
- done
-
- # check
- if [[ ${#option_paths[@]} -eq 0 ]]; then
- help "No s provided."
- fi
-
- # =====================================
- # Action
-
- # call this again, but inside sudo
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- sudo-helper --inherit --user="$option_user" --group="$option_group" \
- -- is-empty-ls -- "${option_paths[@]}"
- return
- fi
-
- local path
- for path in "${option_paths[@]}"; do
- if [[ ! -d $path ]]; then
- echo-error 'A path was was not a directory: ' --code="$path"
- return 2
- fi
- [[ -z "$(ls -A "$path")" ]] || return # explicit return with [[ required for bash v3
- done
- return 0
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_empty_ls "$@"
-fi
diff --git a/commands/is-empty-string b/commands/is-empty-string
deleted file mode 100755
index d9cb688b6..000000000
--- a/commands/is-empty-string
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env bash
-
-function is_empty_string_test() (
- source "$DOROTHY/sources/bash.bash"
- echo-style --h1="TEST: $0"
-
- eval-tester --name='zero-length is empty' \
- -- is-empty-string -- ''
-
- eval-tester --name='space is empty' \
- -- is-empty-string -- $' '
-
- eval-tester --name='newline is empty' \
- -- is-empty-string -- $'\n'
-
- eval-tester --name='tab is empty' \
- -- is-empty-string -- $'\n'
-
- eval-tester --name='whitespace combo is empty' \
- -- is-empty-string -- $'\n\t '
-
- eval-tester --name='letters not empty' --status=1 \
- -- is-empty-string -- 'a'
-
- echo-style --g1="TEST: $0"
- return 0
-)
-function is_empty_string() (
- source "$DOROTHY/sources/bash.bash"
-
- # help
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Check if an input is only whitespace characters.
-
- USAGE:
- is-empty-string [...options] [--]
-
- OPTIONS:
- | --string=
- Verify this is an empty string
-
- RETURNS:
- [0] if all s were empty strings
- [1] if any s were not empty strings
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process
- local item option_inputs=()
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- '--string='*) option_inputs+=("${item#*=}") ;;
- '--')
- option_inputs+=("$@")
- shift $#
- break
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_inputs+=("$item") ;;
- esac
- done
-
- # verify
- if [[ ${#option_inputs[@]} -eq 0 ]]; then
- help 'No s provided.'
- fi
-
- # =====================================
- # Action
-
- local value="${option_inputs[*]}"
- if [[ $value =~ ^[[:space:]]*$ ]]; then
- # value is only whitespace characters
- return 0
- else
- return 1
- fi
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- if [[ $* == '--test' ]]; then
- is_empty_string_test
- else
- is_empty_string "$@"
- fi
-fi
diff --git a/commands/is-empty-value b/commands/is-empty-value
index 67e3e3de7..a2d6438bf 100755
--- a/commands/is-empty-value
+++ b/commands/is-empty-value
@@ -1,5 +1,27 @@
#!/usr/bin/env bash
+function is_empty_value_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-empty-value --
+
+ eval-tester --name='a single empty string is empty' --status= \
+ -- is-empty-value -- ''
+
+ eval-tester --name='empty values are empty' \
+ -- is-empty-value -- '' ' ' $'\t' $'\n' $' \t\n' null NULL void VOID undefined UNDEFINED
+
+ eval-tester --name='any non-empty values is standard failure' --status=1 \
+ -- is-empty-value -- '' ' null'
+
+ eval-tester --name='any non-empty values is standard failure' --status=1 \
+ -- is-empty-value -- '>'
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_empty_value() (
source "$DOROTHY/sources/bash.bash"
@@ -10,6 +32,7 @@ function is_empty_value() (
cat <<-EOF >/dev/stderr
ABOUT:
Check if the input is an empty value.
+ Companion to [is-value], [echo-values]. Equivalent to a [is-nullish].
USAGE:
is-empty-value [...options] [--]
@@ -19,8 +42,8 @@ function is_empty_value() (
Verify this is an empty value
RETURNS:
- [0] if all s were empty values
- [1] if any s were not empty values
+ [0] if all s are empty values
+ [1] if any s are not empty values
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -54,8 +77,8 @@ function is_empty_value() (
# process
local value
for value in "${option_inputs[@]}"; do
- # check for empty values, or check for an empty string
- if [[ -z $value || $value =~ ^(null|NULL|void|VOID|undefined|UNDEFINED)$ ]] || is-empty-string -- "$value"; then
+ # check for empty values, including empty string and all whitespace
+ if [[ $value =~ ^([[:space:]]*|null|NULL|void|VOID|undefined|UNDEFINED)$ ]]; then
: # all good, conntinue
else
return 1 # not good
@@ -66,5 +89,9 @@ function is_empty_value() (
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_empty_value "$@"
+ if [[ $* == '--test' ]]; then
+ is_empty_value_test
+ else
+ is_empty_value "$@"
+ fi
fi
diff --git a/commands/is-even b/commands/is-even
new file mode 100755
index 000000000..e02ed378e
--- /dev/null
+++ b/commands/is-even
@@ -0,0 +1,115 @@
+#!/usr/bin/env bash
+
+function is_even_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-even --
+
+ eval-tester --name='even numbers are even' \
+ -- is-even -- 2 4 6 8 10
+
+ eval-tester --name='megative even numbers are even' \
+ -- is-even -- -2 -4 -6 -8 -10
+
+ eval-tester --name='odd numbers are not even' --status=1 \
+ -- is-even -- 1
+
+ eval-tester --name='odd numbers are not even' --status=1 \
+ -- is-even -- 1 3
+
+ eval-tester --name='zero is valid' \
+ -- is-even -- 0 -0
+
+ eval-tester --name='decimals are invalid' --status=22 --ignore-stderr \
+ -- is-even -- 2.0
+
+ eval-tester --name='even then odd is standard failure' --status=1 \
+ -- is-even -- 2 3
+
+ eval-tester --name='even then odd then invalid is invalid failure' --status=22 --ignore-stderr \
+ -- is-even -- 2 3 2.0
+
+ eval-tester --name='even then invalid then odd is invalid failure' --status=22 --ignore-stderr \
+ -- is-even -- 2 2.0 3
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_even() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ # help
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Checks if the is an even integer.
+ Companion to [is-odd]. Equivalent to a [is-even-integer].
+
+ USAGE:
+ is-even [...options] [--]
+
+ OPTIONS:
+
+ Validate this
+
+ RETURNS:
+ [0] if all s are even integers
+ [1] if any s are not even integers
+ [22] if any s are not integers
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=()
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided'
+ fi
+
+ # verify
+ if ! is-integer -- "${option_inputs[@]}"; then
+ help 's must be integers'
+ fi
+
+ # =====================================
+ # Action
+
+ local input
+ for input in "${option_inputs[@]}"; do
+ [[ $((input % 2)) -eq 0 ]] || return # explicit return with [[ required for bash v3
+ done
+ return 0
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_even_test
+ else
+ is_even "$@"
+ fi
+fi
diff --git a/commands/is-file b/commands/is-file
index 25e12209f..34c3fb22b 100755
--- a/commands/is-file
+++ b/commands/is-file
@@ -1,5 +1,63 @@
#!/usr/bin/env bash
+function is_file_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-file --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-file -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-file -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='directory' --status=1 \
+ -- is-file -- "$DOROTHY"
+
+ eval-tester --name='file' \
+ -- is-file -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir' --status=1 \
+ -- is-file -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='dir then file' --status=1 \
+ -- is-file -- "$DOROTHY" "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir then invalid' --status=1 \
+ -- is-file -- "$DOROTHY/README.md" "$DOROTHY" ''
+
+ eval-tester --name='dir then invalid then dir' --status=22 \
+ -- is-file -- "$DOROTHY/README.md" '' "$DOROTHY"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-file' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-file' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-file' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-file' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' --status=1 \
+ -- is-file -- "$dir_symlink"
+
+ eval-tester --name='symlink file' \
+ -- is-file -- "$file_symlink"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' --status=1 \
+ -- is-file -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' --status=1 \
+ -- is-file -- "$file_symlink"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_file() (
source "$DOROTHY/sources/bash.bash"
@@ -9,7 +67,7 @@ function is_file() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Check if all s are a file (and not a symlink).
+ Check if all s are a file, or an unbroken symlink to a file.
USAGE:
is-file [...options] [--] ...
@@ -22,8 +80,9 @@ function is_file() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were a file
- [1] if any s were not a file
+ [0] if all s are a file, or an unbroken symlink to a file
+ [1] if any s are neither a file, nor an unbroken symlink to a file
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -61,20 +120,15 @@ function is_file() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-file.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-file.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-file.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_file "$@"
+ if [[ $* == '--test' ]]; then
+ is_file_test
+ else
+ is_file "$@"
+ fi
fi
diff --git a/commands/is-file.bash b/commands/is-file.bash
index 1b14605e7..b7b649386 100755
--- a/commands/is-file.bash
+++ b/commands/is-file.bash
@@ -7,7 +7,12 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
- [[ -f $1 && ! -L $1 ]] || exit
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -f $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-generic b/commands/is-generic
index 775065626..be6870b5b 100755
--- a/commands/is-generic
+++ b/commands/is-generic
@@ -4,12 +4,21 @@ function is_generic_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --name='user.local is generic' --status=0 \
- -- is-generic -- 'user.local'
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-generic --
+
+ eval-tester --name='generics are generic' \
+ -- is-generic -- '' $' \t\n' 'user.local' 'USER.LOCAL' 'false' 'null' 'undefined' 'ubuntu' 'root' 'admin' 'super' 'user' 'localhost'
eval-tester --name='custom.local is not generic' --status=1 \
-- is-generic -- 'custom.local'
+ eval-tester --name='mix is not generic' --status=1 \
+ -- is-generic -- 'custom.local' 'false'
+
+ eval-tester --name='custom.localhost is not generic' --status=1 \
+ -- is-generic -- 'custom.localhost'
+
echo-style --g1="TEST: $0"
return 0
)
@@ -19,6 +28,7 @@ function is_generic() (
# =====================================
# Arguments
+ # @note if you want a `[0] if any s were generic` then you want to implement a `! is-not-generic` instead
function help {
cat <<-EOF >/dev/stderr
ABOUT:
@@ -28,8 +38,8 @@ function is_generic() (
is-generic [--] ...
RETURNS:
- [0] if ANY s were generic
- [1] if no s were generic
+ [0] if all s are generic
+ [1] if any s are not generic
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -62,18 +72,16 @@ function is_generic() (
# =====================================
# Action
- local value="${option_inputs[*]}"
- if is-empty-value -- "$value"; then
- return 0 # generic
- else
- value="$(__lowercase_string -- "$value")"
- value="${value%.local}" # trim .local
- if [[ $value =~ ^(false|null|undefined|ubuntu|root|admin|super|user|localhost)$ ]]; then
- return 0
- else
- return 1
- fi
- fi
+ local input
+ for input in "${option_inputs[@]}"; do
+ # lowercase
+ input="$(__lowercase_string -- "$input")"
+ # trim .local
+ input="${input%.local}"
+ # check for generic values
+ [[ $input =~ ^([[:space:]]*|false|null|undefined|ubuntu|root|admin|super|user|localhost)$ ]] || return # explicit return with [[ required for bash v3
+ done
+ return 0
)
# fire if invoked standalone
diff --git a/commands/is-globstar b/commands/is-globstar
index ab19cf606..b5e073b9d 100755
--- a/commands/is-globstar
+++ b/commands/is-globstar
@@ -16,7 +16,7 @@ function is_globstar_test() (
eval-tester --name='star string' --status=1 \
-- is-globstar -- ' /Users/runner/.cache/dorothy/*/unziptar/5241/rg'
- eval-tester --name='globstar string' --status=0 \
+ eval-tester --name='globstar string' \
-- is-globstar -- ' /Users/runner/.cache/dorothy/**/unziptar/5241/rg'
echo-style --g1="TEST: $0"
@@ -37,8 +37,8 @@ function is_globstar() (
is-globstar [--] ...
RETURNS:
- [0] if ANY s were generic
- [1] if no s were generic
+ [0] if ANY s are generic
+ [1] if no s are generic
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-group b/commands/is-group
index d24d73723..8444dc05e 100755
--- a/commands/is-group
+++ b/commands/is-group
@@ -19,8 +19,8 @@ function is_group() (
Verify this is registered as a group on the system.
RETURNS:
- [0] if all s were a group on the system.
- [1] if any s were not a group on the system.
+ [0] if all s are a group on the system.
+ [1] if any s are not a group on the system.
[19] if the OS is not supported.
EOF
if [[ $# -ne 0 ]]; then
diff --git a/commands/is-integer b/commands/is-integer
index c08372b5b..41e8bcd8f 100755
--- a/commands/is-integer
+++ b/commands/is-integer
@@ -17,13 +17,13 @@ function is_integer_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --name='zero' --status=0 \
+ eval-tester --name='zero' \
-- is-integer -- 0
- eval-tester --name='one' --status=0 \
+ eval-tester --name='one' \
-- is-integer -- 1
- eval-tester --name='ten' --status=0 \
+ eval-tester --name='ten' \
-- is-integer -- 10
eval-tester --name='decimal' --status=1 \
@@ -32,10 +32,10 @@ function is_integer_test() (
eval-tester --name='triple decimal' --status=1 \
-- is-integer -- 1.1.1
- eval-tester --name='negative' --status=0 \
+ eval-tester --name='negative' \
-- is-integer -- -1
- eval-tester --name='negative 10' --status=0 \
+ eval-tester --name='negative 10' \
-- is-integer -- -10
eval-tester --name='negative decimal' --status=1 \
@@ -65,7 +65,8 @@ function is_integer() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Checks if the is an integer (non-decimal number)
+ Checks if the is an integer (non-decimal number).
+ Companion to [is-number] and [is-digit].
USAGE:
is-integer [...options] [--]
@@ -75,8 +76,8 @@ function is_integer() (
Verify this is an integer
RETURNS:
- [0] if all s were integer
- [1] if any s were not integers
+ [0] if all s are integers
+ [1] if any s are not integers
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-missing b/commands/is-missing
index b17737f43..0e33b206d 100755
--- a/commands/is-missing
+++ b/commands/is-missing
@@ -1,5 +1,62 @@
#!/usr/bin/env bash
+function is_missing_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-missing --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-missing -- '' ''
+
+ eval-tester --name='directory' --status=1 \
+ -- is-missing -- "$DOROTHY"
+
+ eval-tester --name='missing' \
+ -- is-missing -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='file' --status=1 \
+ -- is-missing -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir' --status=1 \
+ -- is-missing -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='missing then file' --status=1 \
+ -- is-missing -- "$DOROTHY/this-doesnt-exist" "$DOROTHY/README.md"
+
+ eval-tester --name='missing then file then invalid' --status=1 \
+ -- is-missing -- "$DOROTHY/this-doesnt-exist" "$DOROTHY/README.md" ''
+
+ eval-tester --name='missing then invalid then file' --status=22 \
+ -- is-missing -- "$DOROTHY/this-doesnt-exist" '' "$DOROTHY/README.md"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-missing' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-missing' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-missing' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-missing' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' --status=1 \
+ -- is-missing -- "$dir_symlink"
+
+ eval-tester --name='symlink file' --status=1 \
+ -- is-missing -- "$file_symlink"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' --status=1 \
+ -- is-missing -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' --status=1 \
+ -- is-missing -- "$file_symlink"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_missing() (
source "$DOROTHY/sources/bash.bash"
@@ -9,8 +66,8 @@ function is_missing() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Check if all s are missing (not a file/directory/symlink).
- Opposite of [is-present].
+ Check if all s are missing (not a file/directory/symlink/broken-symlink).
+ Companion to [is-present]. Equivalent to a [is-missing-path], [is-path-missing].
USAGE:
is-missing [...options] [--] ...
@@ -23,8 +80,9 @@ function is_missing() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were missing
- [1] if any s were not missing
+ [0] if all s are missing (not even a broken symlink)
+ [1] if any s are not missing
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -62,20 +120,15 @@ function is_missing() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-missing.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-missing.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-missing.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_missing "$@"
+ if [[ $* == '--test' ]]; then
+ is_missing_test
+ else
+ is_missing "$@"
+ fi
fi
diff --git a/commands/is-missing.bash b/commands/is-missing.bash
index 5e5a5d302..4e175427a 100755
--- a/commands/is-missing.bash
+++ b/commands/is-missing.bash
@@ -7,8 +7,13 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
# just -e is faulty, as -e fails on broken symlinks
- [[ ! -e $1 && ! -L $1 ]] || exit
+ if [[ -e $1 || -L $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-needle b/commands/is-needle
index 66e0e5064..86efdb76a 100755
--- a/commands/is-needle
+++ b/commands/is-needle
@@ -27,13 +27,13 @@ function is_needle_test() (
eval-tester --status=1 \
-- is-needle b c -- a 'b b b'
- eval-tester --status=0 \
+ eval-tester \
-- is-needle a 'b b b' -- a 'b b b'
- eval-tester --status=0 \
+ eval-tester \
-- is-needle --needle=a --needle='b b b' -- a 'b b b'
- eval-tester --status=0 \
+ eval-tester \
-- is-needle a a -- a 'b b b'
eval-tester --status=1 \
@@ -52,6 +52,7 @@ function is_needle() (
cat <<-EOF >/dev/stderr
ABOUT:
Check if the exists within the s
+ Equivalent to a [is-either], [is-neither].
USAGE:
is-needle [...options] [--] ...
@@ -62,8 +63,8 @@ function is_needle() (
Note that you should always use [--needle=] as just doing will fail if the looks like a flag.
RETURNS:
- [0] if all s were found within the s
- [1] if any was not found
+ [0] if all s are found within the s
+ [1] if any s are not found
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-non-affirmative b/commands/is-non-affirmative
index b0e07c834..c40fd2b07 100755
--- a/commands/is-non-affirmative
+++ b/commands/is-non-affirmative
@@ -10,6 +10,7 @@ function __is_non_affirmative() (
cat <<-EOF >/dev/stderr
ABOUT:
Check if is a non-affirmative value.
+ Companion to [is-affirmative].
USAGE:
is-non-affirmative [...options] [--] ...
@@ -22,9 +23,9 @@ function __is_non_affirmative() (
Ignore/skip empty values.
RETURNS:
- [0] if all s were non-affirmative
- [1] if any was affirmative
- [91] if invalid values were provided, or no s were provided
+ [0] if all s are non-affirmative
+ [1] if any s are affirmative
+ [91] if invalid values are provided, or no s are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@" || return
diff --git a/commands/is-nonempty-string b/commands/is-nonempty-string
deleted file mode 100755
index 2ef5a96bb..000000000
--- a/commands/is-nonempty-string
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-
-function is_nonempty_string() (
- source "$DOROTHY/sources/bash.bash"
-
- # help
- function help {
- cat <<-EOF >/dev/stderr
- ABOUT:
- Check if the input is not just whitespace characters.
-
- USAGE:
- is-nonempty-string [--] ...
- EOF
- if [[ $# -ne 0 ]]; then
- echo-error "$@"
- fi
- return 22 # EINVAL 22 Invalid argument
- }
-
- # process our arguments
- local item option_inputs=()
- while [[ $# -ne 0 ]]; do
- item="$1"
- shift
- case "$item" in
- '--help' | '-h') help ;;
- --)
- option_inputs+=("$@")
- shift $#
- ;;
- '--'*) help "An unrecognised flag was provided: $item" ;;
- *) option_inputs+=("$item") ;;
- esac
- done
-
- # adjust
- if [[ ${#option_inputs[@]} -eq 0 ]]; then
- help 'No s provided.'
- fi
- local value="${option_inputs[*]}"
-
- # process
- if is-empty-string -- "$value"; then
- return 1
- else
- return 0
- fi
-)
-
-# fire if invoked standalone
-if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_nonempty_string "$@"
-fi
diff --git a/commands/is-not-directory b/commands/is-not-directory
index 18409460c..eeba6bd46 100755
--- a/commands/is-not-directory
+++ b/commands/is-not-directory
@@ -9,7 +9,10 @@ function is_not_directory() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Check if all s are not a directory.
+ Check if all s are neither a directory, nor an unbroken symlink to a directory.
+ Companion to [is-directory].
+ If you want if any are not directory, use [! is-directory -- ...].
+ The advantage of using this over [! is-directory -- ...] is that will pass for invalid paths and arguments.
USAGE:
is-not-directory [...options] [--] ...
@@ -22,8 +25,9 @@ function is_not_directory() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were not a directory
- [1] if any s was a directory or symlink
+ [0] if all s were neither a directory, nor an unbroken symlink to a directory
+ [1] if any s were a directory, or an unbroken symlink to a directory
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -61,17 +65,8 @@ function is_not_directory() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-not-directory.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-not-directory.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-not-directory.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
diff --git a/commands/is-not-directory.bash b/commands/is-not-directory.bash
index 0f9b168fe..d80f63786 100755
--- a/commands/is-not-directory.bash
+++ b/commands/is-not-directory.bash
@@ -7,7 +7,12 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
- [[ ! -d $1 || -L $1 ]] || exit
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ -d $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-not-symlink b/commands/is-not-symlink
new file mode 100755
index 000000000..d194cae52
--- /dev/null
+++ b/commands/is-not-symlink
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+
+function is_not_symlink_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-not-symlink --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-not-symlink -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-not-symlink -- "$DOROTHY/this-doesnt-exist"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-not-symlink' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-not-symlink' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-not-symlink' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-not-symlink' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ # #2todo
+ eval-tester --name='symlink dir' \
+ -- is-not-symlink -- "$dir_symlink"
+
+ eval-tester --name='symlink file' \
+ -- is-not-symlink -- "$file_symlink"
+
+ eval-tester --name='symlink dir then dir' --status=1 \
+ -- is-not-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='symlink file then file' --status=1 \
+ -- is-not-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='symlink file then missing' --status=1 \
+ -- is-not-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' \
+ -- is-not-symlink -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' \
+ -- is-not-symlink -- "$file_symlink"
+
+ eval-tester --name='broken symlink dir then dir' --status=1 \
+ -- is-not-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='broken symlink file then file' --status=1 \
+ -- is-not-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='broken symlink file then missing' --status=1 \
+ -- is-not-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_not_symlink() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Check if all s are not a symlink, broken or otherwise.
+
+ USAGE:
+ is-not-symlink [...options] [--] ...
+
+ OPTIONS:
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ RETURNS:
+ [0] if all s were not a symlink
+ [1] if any s were a symlink
+ [22] if empty arguments are provided
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided.'
+ fi
+
+ # =====================================
+ # Action
+
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-not-symlink.bash -- "${option_inputs[@]}"
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_not_symlink_test
+ else
+ is_not_symlink "$@"
+ fi
+fi
diff --git a/commands/is-not-symlink.bash b/commands/is-not-symlink.bash
new file mode 100755
index 000000000..8ed999483
--- /dev/null
+++ b/commands/is-not-symlink.bash
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ -L $1 ]]; then
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands/is-not-whitespace b/commands/is-not-whitespace
new file mode 100755
index 000000000..5c0909c67
--- /dev/null
+++ b/commands/is-not-whitespace
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+function is_not_whitespace_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-not-whitespace --
+
+ eval-tester --name='zero-length is standard failure' --status=1 \
+ -- is-not-whitespace -- '' ''
+
+ eval-tester --name='space is standard failure' --status=1 \
+ -- is-not-whitespace -- ' ' ' '
+
+ eval-tester --name='newline is standard failure' --status=1 \
+ -- is-not-whitespace -- $'\n' $'\n'
+
+ eval-tester --name='newline and tab is standard failure' --status=1 \
+ -- is-not-whitespace -- $'\n' $'\t'
+
+ eval-tester --name='whitespace combo is standard failure' --status=1 \
+ -- is-not-whitespace -- $'\n\t '
+
+ eval-tester --name='letters and numbers' \
+ -- is-not-whitespace -- 'a' 0
+
+ eval-tester --name='mix is is stsandard failure pt. 1' --status=1 \
+ -- is-not-whitespace -- '' 'b'
+
+ eval-tester --name='mix is is stsandard failure pt. 2' --status=1 \
+ -- is-not-whitespace -- 'a' ''
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_not_whitespace() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # help
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Check if the input is not just whitespace characters.
+ Companion to [is-whitespace], [echo-trim-empty-lines]. Equivalent to a [is-string], [is-blackspace], [is-notempty-string], [is-not-empty-string], [is-not-only-whitespace], [is-non-whitespace].
+
+ USAGE:
+ is-not-whitespace [...options] [--]
+
+ OPTIONS:
+ | --string=
+ Verify this is a non-empty string
+
+ RETURNS:
+ [0] if all s are non-whitespace strings
+ [1] if any s are not non-whitespace strings
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process our arguments
+ local item option_inputs=()
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ --)
+ option_inputs+=("$@")
+ shift $#
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # adjust
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided.'
+ fi
+
+ # =====================================
+ # Action
+
+ # fails mixed test case:
+ # [[ ! ${option_inputs[*]} =~ ^[[:space:]]*$ ]]
+ # return
+
+ local input
+ for input in "${option_inputs[@]}"; do
+ if [[ $input =~ ^[[:space:]]*$ ]]; then
+ return 1
+ fi
+ done
+ return 0
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_not_whitespace_test
+ else
+ is_not_whitespace "$@"
+ fi
+fi
diff --git a/commands/is-number b/commands/is-number
index 4492e7340..c3a669da9 100755
--- a/commands/is-number
+++ b/commands/is-number
@@ -4,28 +4,28 @@ function is_number_test() (
source "$DOROTHY/sources/bash.bash"
echo-style --h1="TEST: $0"
- eval-tester --name='zero IS a number' --status=0 \
+ eval-tester --name='zero IS a number' \
-- is-number -- 0
- eval-tester --name='one IS a number' --status=0 \
+ eval-tester --name='one IS a number' \
-- is-number -- 1
- eval-tester --name='ten IS a number' --status=0 \
+ eval-tester --name='ten IS a number' \
-- is-number -- 10
- eval-tester --name='decimal IS a number' --status=0 \
+ eval-tester --name='decimal IS a number' \
-- is-number -- 0.1
eval-tester --name='triple decimal IS NOT a number' --status=1 \
-- is-number -- 1.1.1
- eval-tester --name='negative IS a number' --status=0 \
+ eval-tester --name='negative IS a number' \
-- is-number -- -1
- eval-tester --name='negative 10 IS a number' --status=0 \
+ eval-tester --name='negative 10 IS a number' \
-- is-number -- -10
- eval-tester --name='negative decimal IS a number' --status=0 \
+ eval-tester --name='negative decimal IS a number' \
-- is-number -- -1.1
eval-tester --name='negative triple decimal IS NOT a number' --status=1 \
@@ -57,6 +57,7 @@ function is_number() (
cat <<-EOF >/dev/stderr
ABOUT:
Checks if the is a valid number.
+ Companion to [is-integer] and [is-digit].
USAGE:
is-number [...options] [--]
@@ -66,8 +67,8 @@ function is_number() (
Verify this is a valid number
RETURNS:
- [0] if all s were valid numbers
- [1] if any s were not valid numbers
+ [0] if all s are valid numbers
+ [1] if any s are not valid numbers
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-odd b/commands/is-odd
index a93712dff..b428675b8 100755
--- a/commands/is-odd
+++ b/commands/is-odd
@@ -1,5 +1,42 @@
#!/usr/bin/env bash
+function is_odd_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-odd --
+
+ eval-tester --name='odd numbers are odd' \
+ -- is-odd -- 1 3 5 7 9 11
+
+ eval-tester --name='megative odd numbers are odd' \
+ -- is-odd -- -1 -3 -5 -7 -9 -11
+
+ eval-tester --name='even numbers are not odd' --status=1 \
+ -- is-odd -- 2
+
+ eval-tester --name='even numbers are not odd' --status=1 \
+ -- is-odd -- 2 4
+
+ eval-tester --name='zero is not odd' --status=1 \
+ -- is-odd -- 0 -0
+
+ eval-tester --name='decimals are invalid' --status=22 --ignore-stderr \
+ -- is-odd -- 1.1
+
+ eval-tester --name='odd then even is standard failure' --status=1 \
+ -- is-odd -- 1 2
+
+ eval-tester --name='odd then even then invalid is invalid failure' --status=22 --ignore-stderr \
+ -- is-odd -- 1 2 1.1
+
+ eval-tester --name='odd then invalid then odd is invalid failure' --status=22 --ignore-stderr \
+ -- is-odd -- 1 1.1 2
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_odd() (
source "$DOROTHY/sources/bash.bash"
@@ -10,19 +47,20 @@ function is_odd() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Checks if the is an odd number.
+ Checks if the is an odd integer.
+ Companion to [is-even]. Equivalent to a [is-odd-integer].
USAGE:
is-odd [...options] [--]
OPTIONS:
- Verify this is an odd number
+ Validate this
RETURNS:
- [0] if all s were odd numbers
- [1] if any s were not odd numbers
- [2] if any s were not numbers
+ [0] if all s are odd integers
+ [1] if any s are not odd integers
+ [22] if any s are not integers
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -49,12 +87,12 @@ function is_odd() (
# verify
if [[ ${#option_inputs[@]} -eq 0 ]]; then
- help "No s provided"
+ help 'No s provided'
fi
# verify
- if ! is-number -- "${option_inputs[@]}"; then
- return 2
+ if ! is-integer -- "${option_inputs[@]}"; then
+ help 's must be integers'
fi
# =====================================
@@ -62,12 +100,16 @@ function is_odd() (
local input
for input in "${option_inputs[@]}"; do
- [[ "$((input % 2))" -ne 0 ]] || return # explicit return with [[ required for bash v3
+ [[ $((input % 2)) -ne 0 ]] || return # explicit return with [[ required for bash v3
done
return 0
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_odd "$@"
+ if [[ $* == '--test' ]]; then
+ is_odd_test
+ else
+ is_odd "$@"
+ fi
fi
diff --git a/commands/is-present b/commands/is-present
index 25692edbc..48f809259 100755
--- a/commands/is-present
+++ b/commands/is-present
@@ -1,5 +1,62 @@
#!/usr/bin/env bash
+function is_present_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-present --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-present -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-present -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='directory' \
+ -- is-present -- "$DOROTHY"
+
+ eval-tester --name='file' \
+ -- is-present -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir' \
+ -- is-present -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='dir then file' \
+ -- is-present -- "$DOROTHY" "$DOROTHY/README.md"
+
+ eval-tester --name='dir then file then invalid' --status=22 \
+ -- is-present -- "$DOROTHY" "$DOROTHY/README.md" ''
+
+ eval-tester --name='dir then invalid then file' --status=22 \
+ -- is-present -- "$DOROTHY" '' "$DOROTHY/README.md"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-present' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-present' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-present' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-present' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' \
+ -- is-present -- "$dir_symlink"
+
+ eval-tester --name='symlink file' \
+ -- is-present -- "$file_symlink"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' --status=1 \
+ -- is-present -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' --status=1 \
+ -- is-present -- "$file_symlink"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_present() (
source "$DOROTHY/sources/bash.bash"
@@ -9,11 +66,11 @@ function is_present() (
function help {
cat <<-EOF >/dev/stderr
ABOUT:
- Check if all s are present (file/directory/symlink).
- Opposite of [is-missing].
+ Check if all s are present (file/directory/symlink/broken-symlink).
+ Companion to [is-missing].
USAGE:
- is-presen [...options] [--] ...
+ is-present [...options] [--] ...
OPTIONS:
--sudo
@@ -23,8 +80,9 @@ function is_present() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were present
+ [0] if all s were present (even if it is a broken symlink).
[1] if any s were not present
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -62,20 +120,15 @@ function is_present() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-present.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-present.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-present.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_present "$@"
+ if [[ $* == '--test' ]]; then
+ is_present_test
+ else
+ is_present "$@"
+ fi
fi
diff --git a/commands/is-present.bash b/commands/is-present.bash
index 062a50895..bab63034f 100755
--- a/commands/is-present.bash
+++ b/commands/is-present.bash
@@ -7,8 +7,13 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
# just -e is faulty, as -e fails on broken symlinks
- [[ -e $1 || -L $1 ]] || exit
+ if ! [[ -e $1 || -L $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-readable b/commands/is-readable
index 9657826df..14e1c8a26 100755
--- a/commands/is-readable
+++ b/commands/is-readable
@@ -1,5 +1,62 @@
#!/usr/bin/env bash
+function is_readable_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-readable --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-readable -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-readable -- "$DOROTHY/this-doesnt-exist"
+
+ eval-tester --name='directory' \
+ -- is-readable -- "$DOROTHY"
+
+ eval-tester --name='file' \
+ -- is-readable -- "$DOROTHY/README.md"
+
+ eval-tester --name='file then dir' \
+ -- is-readable -- "$DOROTHY/README.md" "$DOROTHY"
+
+ eval-tester --name='dir then file' \
+ -- is-readable -- "$DOROTHY" "$DOROTHY/README.md"
+
+ eval-tester --name='dir then file then missing then invalid' --status=1 \
+ -- is-readable -- "$DOROTHY" "$DOROTHY/README.md" "$DOROTHY/this-doesnt-exist" ''
+
+ eval-tester --name='dir then invalid then missing then file' --status=22 \
+ -- is-readable -- "$DOROTHY" '' "$DOROTHY/this-doesnt-exist" "$DOROTHY/README.md"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-readable' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-readable' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-readable' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-readable' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' \
+ -- is-readable -- "$dir_symlink"
+
+ eval-tester --name='symlink file' \
+ -- is-readable -- "$file_symlink"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' --status=1 \
+ -- is-readable -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' --status=1 \
+ -- is-readable -- "$file_symlink"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
function is_readable() (
source "$DOROTHY/sources/bash.bash"
@@ -22,8 +79,9 @@ function is_readable() (
If specified use this user and/or group for filesystem interactions.
RETURNS:
- [0] if all s were readable
- [1] if any s were not readable
+ [0] if all s are readable
+ [1] if any s are not readable
+ [22] if empty arguments are provided
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
@@ -61,20 +119,15 @@ function is_readable() (
# =====================================
# Action
- local input
- if [[ $option_sudo == 'yes' || -n $option_user || -n $option_group ]]; then
- for input in "${option_inputs[@]}"; do
- sudo-helper --inherit --user="$option_user" --group="$option_group" -- is-readable.bash -- "$input" || return
- done
- else
- for input in "${option_inputs[@]}"; do
- is-readable.bash -- "$input" || return
- done
- fi
- return 0
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-readable.bash -- "${option_inputs[@]}"
+ return
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
- is_readable "$@"
+ if [[ $* == '--test' ]]; then
+ is_readable_test
+ else
+ is_readable "$@"
+ fi
fi
diff --git a/commands/is-readable.bash b/commands/is-readable.bash
index c9ba9deab..23208a3f6 100755
--- a/commands/is-readable.bash
+++ b/commands/is-readable.bash
@@ -7,7 +7,12 @@ if [[ $# -eq 0 ]]; then
exit 22 # EINVAL 22 Invalid argument
fi
while [[ $# -ne 0 ]]; do
- [[ -r $1 ]] || exit
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -r $1 ]]; then
+ exit 1
+ fi
shift
done
exit 0
diff --git a/commands/is-same b/commands/is-same
index 79e8faf4d..c8416ac0d 100755
--- a/commands/is-same
+++ b/commands/is-same
@@ -89,8 +89,8 @@ function is_same() (
# same structure
local first_structure second_structure
- first_structure="$(fs-structure -- "$first_path")"
- second_structure="$(fs-structure -- "$second_path")"
+ first_structure="$(fs-structure --no-perms --no-time -- "$first_path")"
+ second_structure="$(fs-structure --no-perms --no-time -- "$second_path")"
if [[ $first_structure != "$second_structure" ]]; then
echo-style \
--header1="$first_path" $'\n' \
diff --git a/commands/is-symlink b/commands/is-symlink
new file mode 100755
index 000000000..ba9e64ace
--- /dev/null
+++ b/commands/is-symlink
@@ -0,0 +1,133 @@
+#!/usr/bin/env bash
+
+function is_symlink_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-symlink --
+
+ eval-tester --name='empty args' --status=22 \
+ -- is-symlink -- '' ''
+
+ eval-tester --name='missing' --status=1 \
+ -- is-symlink -- "$DOROTHY/this-doesnt-exist"
+
+ # test working symlinks
+ local dir_target dir_symlink file_target file_symlink
+ dir_target="$(fs-temp --directory='is-symlink' --directory='dir_target' --touch)"
+ file_target="$(fs-temp --directory='is-symlink' --file='file_target' --touch)"
+ dir_symlink="$(fs-temp --directory='is-symlink' --directory='dir_symlink' --no-touch)"
+ file_symlink="$(fs-temp --directory='is-symlink' --file='file_symlink' --no-touch)"
+ symlink-helper --existing="$dir_target" --symlink="$dir_symlink" --quiet
+ symlink-helper --existing="$file_target" --symlink="$file_symlink" --quiet
+
+ eval-tester --name='symlink dir' \
+ -- is-symlink -- "$dir_symlink"
+
+ eval-tester --name='symlink file' \
+ -- is-symlink -- "$file_symlink"
+
+ eval-tester --name='symlink dir then dir' --status=1 \
+ -- is-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='symlink file then file' --status=1 \
+ -- is-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='symlink file then missing' --status=1 \
+ -- is-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ # test broken symlinks
+ fs-rm --quiet --no-confirm -- "$dir_target" "$file_target"
+
+ eval-tester --name='broken symlink dir' \
+ -- is-symlink -- "$dir_symlink"
+
+ eval-tester --name='broken symlink file' \
+ -- is-symlink -- "$file_symlink"
+
+ eval-tester --name='broken symlink dir then dir' --status=1 \
+ -- is-symlink -- "$dir_symlink" "$DOROTHY"
+
+ eval-tester --name='broken symlink file then file' --status=1 \
+ -- is-symlink -- "$file_symlink" "$DOROTHY/README.md"
+
+ eval-tester --name='broken symlink file then missing' --status=1 \
+ -- is-symlink -- "$file_symlink" "$DOROTHY/this-doesnt-exist"
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_symlink() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # =====================================
+ # Arguments
+
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Check if all s are a symlink, broken or otherwise.
+
+ USAGE:
+ is-symlink [...options] [--] ...
+
+ OPTIONS:
+ --sudo
+ If specified, use sudo on filesystem interactions.
+ --user=
+ --group=
+ If specified use this user and/or group for filesystem interactions.
+
+ RETURNS:
+ [0] if all s were a symlink
+ [1] if any s were not a symlink
+ [22] if empty arguments are provided
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=() option_sudo='no' option_user='' option_group=''
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
+ '--user='*) option_user="${item#*=}" ;;
+ '--group='*) option_group="${item#*=}" ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided.'
+ fi
+
+ # =====================================
+ # Action
+
+ sudo-helper --inherit --sudo="$option_sudo" --user="$option_user" --group="$option_group" -- is-symlink.bash -- "${option_inputs[@]}"
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_symlink_test
+ else
+ is_symlink "$@"
+ fi
+fi
diff --git a/commands/is-symlink.bash b/commands/is-symlink.bash
new file mode 100755
index 000000000..5468e6d31
--- /dev/null
+++ b/commands/is-symlink.bash
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+if [[ $1 == '--' ]]; then
+ shift
+fi
+if [[ $# -eq 0 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+fi
+while [[ $# -ne 0 ]]; do
+ if [[ -z $1 ]]; then
+ exit 22 # EINVAL 22 Invalid argument
+ fi
+ if [[ ! -L $1 ]]; then
+ exit 1
+ fi
+ shift
+done
+exit 0
diff --git a/commands/is-user b/commands/is-user
index d3a36668e..35ccf2e80 100755
--- a/commands/is-user
+++ b/commands/is-user
@@ -20,8 +20,8 @@ function is_user() (
Verify this is registered as a user on the system.
RETURNS:
- [0] if all s were a user on the system.
- [1] if any s were not a user on the system.
+ [0] if all s are a user on the system.
+ [1] if any s are not a user on the system.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-user-in-group b/commands/is-user-in-group
index 88c2d2cab..503b72398 100755
--- a/commands/is-user-in-group
+++ b/commands/is-user-in-group
@@ -22,8 +22,8 @@ function is_user_in_group() (
A user to check is within the s.
RETURNS:
- [0] if all s were within .
- [1] if any s were not within .
+ [0] if all s are within .
+ [1] if any s are not within .
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-value b/commands/is-value
index a92506d16..ac7ffd106 100755
--- a/commands/is-value
+++ b/commands/is-value
@@ -10,6 +10,7 @@ function is_value() (
cat <<-EOF >/dev/stderr
ABOUT:
Check if the is a non-empty value.
+ Companion to [is-empty-value].
USAGE:
is-value [...options] [--]
@@ -19,8 +20,8 @@ function is_value() (
Verify this is an empty value
RETURNS:
- [0] if all s were not empty values.
- [1] if any s were an empty value.
+ [0] if all s are not empty values.
+ [1] if any s are an empty value.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
diff --git a/commands/is-whitespace b/commands/is-whitespace
new file mode 100755
index 000000000..b0f5a4cda
--- /dev/null
+++ b/commands/is-whitespace
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+
+function is_whitespace_test() (
+ source "$DOROTHY/sources/bash.bash"
+ echo-style --h1="TEST: $0"
+
+ eval-tester --name='no args' --status=22 --ignore-stderr \
+ -- is-whitespace --
+
+ eval-tester --name='zero-length' \
+ -- is-whitespace -- '' ''
+
+ eval-tester --name='space' \
+ -- is-whitespace -- ' ' ' '
+
+ eval-tester --name='newline' \
+ -- is-whitespace -- $'\n' $'\n'
+
+ eval-tester --name='newline and tab' \
+ -- is-whitespace -- $'\n' $'\t'
+
+ eval-tester --name='whitespace combo' \
+ -- is-whitespace -- $'\n\t '
+
+ eval-tester --name='letters is standard failure' --status=1 \
+ -- is-whitespace -- 'a' 'b'
+
+ eval-tester --name='mix is standard failure pt. 1' --status=1 \
+ -- is-whitespace -- '' 'b'
+
+ eval-tester --name='mix is standard failure pt. 2' --status=1 \
+ -- is-whitespace -- 'a' ''
+
+ echo-style --g1="TEST: $0"
+ return 0
+)
+function is_whitespace() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # help
+ function help {
+ cat <<-EOF >/dev/stderr
+ ABOUT:
+ Check if an input is only whitespace characters.
+ Companion to [is-not-whitespace], [echo-trim-empty-lines]. Equivalent to a [is-empty-string], [is-only-whitespace].
+
+ USAGE:
+ is-whitespace [...options] [--]
+
+ OPTIONS:
+ | --string=
+ Verify this is an empty string
+
+ RETURNS:
+ [0] if all s are empty strings
+ [1] if any s are not empty strings
+ EOF
+ if [[ $# -ne 0 ]]; then
+ echo-error "$@"
+ fi
+ return 22 # EINVAL 22 Invalid argument
+ }
+
+ # process
+ local item option_inputs=()
+ while [[ $# -ne 0 ]]; do
+ item="$1"
+ shift
+ case "$item" in
+ '--help' | '-h') help ;;
+ '--string='*) option_inputs+=("${item#*=}") ;;
+ '--')
+ option_inputs+=("$@")
+ shift $#
+ break
+ ;;
+ '--'*) help "An unrecognised flag was provided: $item" ;;
+ *) option_inputs+=("$item") ;;
+ esac
+ done
+
+ # verify
+ if [[ ${#option_inputs[@]} -eq 0 ]]; then
+ help 'No s provided.'
+ fi
+
+ # =====================================
+ # Action
+
+ # local input
+ # for input in "${option_inputs[@]}"; do
+ # if [[ ! $input =~ ^[[:space:]]*$ ]]; then
+ # return 1
+ # fi
+ # done
+ # return 0
+
+ [[ ${option_inputs[*]} =~ ^[[:space:]]*$ ]]
+ return
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ if [[ $* == '--test' ]]; then
+ is_whitespace_test
+ else
+ is_whitespace "$@"
+ fi
+fi
diff --git a/commands/secret b/commands/secret
index 50a668227..df097838a 100755
--- a/commands/secret
+++ b/commands/secret
@@ -497,21 +497,21 @@ function secret_() (
# section fields
local fields_via_section
mapfile -t fields_via_section < <(__print_lines "$data" > >(jq -r '.details.sections[]? | select(.fields).fields[]? | select(.t != "" and .v != "") | (.v, .t)'))
- if is-array-count-ge --size=2 -- "${fields_via_section[@]}"; then
+ if [[ ${#fields_via_section[@]} -ge 2 ]]; then
__print_lines "${fields_via_section[@]}"
fi
# name fields
local fields_via_name
mapfile -t fields_via_name < <(__print_lines "$data" > >(jq -r '.details.fields[]? | select(.name != "" and .value != "") | (.value, .name)'))
- if is-array-count-ge --size=2 -- "${fields_via_name[@]}"; then
+ if [[ ${#fields_via_name[@]} -ge 2 ]]; then
__print_lines "${fields_via_name[@]}"
fi
# designation fields
local fields_via_designation
mapfile -t fields_via_designation < <(__print_lines "$data" > >(jq -r '.details.fields[]? | select(.designation != "" and .value != "") | (.value, .designation)'))
- if is-array-count-ge --size=2 -- "${fields_via_designation[@]}"; then
+ if [[ ${#fields_via_designation[@]} -ge 2 ]]; then
__print_lines "${fields_via_designation[@]}"
fi
fi
@@ -526,7 +526,7 @@ function secret_() (
# fetch available vaults
mapfile -t tuples < <(op_grab)
- if is-array-empty -- "${tuples[@]}"; then
+ if [[ ${#tuples[@]} -eq 0 ]]; then
echo-error "Failed to fetch a vault:" $'\n' \
"$(echo-verbose -- "${tuples[@]}")"
return 1
@@ -544,7 +544,7 @@ function secret_() (
# fetch available items
mapfile -t tuples < <(op_grab "$vault")
- if is-array-empty -- "${tuples[@]}"; then
+ if [[ ${#tuples[@]} -eq 0 ]]; then
echo-error "Failed to fetch any items:" $'\n' \
"$(echo-verbose -- "${tuples[@]}")"
return 1
@@ -568,7 +568,7 @@ function secret_() (
# fetch available items
mapfile -t tuples < <(op_grab "$vault" "$item")
- if is-array-empty -- "${tuples[@]}"; then
+ if [[ ${#tuples[@]} -eq 0 ]]; then
echo-error "Failed to fetch any items:" $'\n' \
"$(echo-verbose -- "${tuples[@]}")"
return 1
@@ -753,15 +753,16 @@ function secret_() (
esac
done
- if [[ $found == 'yes' ]] && is-array-full -- "${before[@]}" && is-array-full -- "${after[@]}"; then
+ # esure we have valid arguments, before -- and after --
+ if [[ $found == 'yes' ]] && is-not-whitespace -- "${before[@]}" && is-not-whitespace -- "${after[@]}"; then
keys=("${before[@]}")
args=("${after[@]}")
else
__print_lines "found = $found"
- __print_lines 'after ='
- echo-verbose -- "${after[@]}"
__print_lines 'before ='
echo-verbose -- "${before[@]}"
+ __print_lines 'after ='
+ echo-verbose -- "${after[@]}"
help "env action requires [--] separator"
fi
diff --git a/commands/setup-dns b/commands/setup-dns
index 748944a43..f3e2311c5 100755
--- a/commands/setup-dns
+++ b/commands/setup-dns
@@ -519,8 +519,8 @@ function setup_dns() (
sudo-helper -- resolvectl reset-server-features --no-pager || :
# apply the changes to their interfaces
- mapfile -t interfaces < <(network-interface list)
- if is-array-empty -- "${interfaces[@]}"; then
+ mapfile -t interfaces < <(network-interface list | echo-values --stdin)
+ if test "${#interfaces[@]}" -eq 0; then
echo-style --error1='No interfaces were found.' >/dev/stderr
return 1
fi
diff --git a/commands/setup-util-qpdf b/commands/setup-util-qpdf
new file mode 100755
index 000000000..edb42d572
--- /dev/null
+++ b/commands/setup-util-qpdf
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+# Tools for and transforming and inspecting PDF files
+# https://github.com/qpdf/qpdf
+
+function setup_util_qpdf() (
+ source "$DOROTHY/sources/bash.bash"
+
+ # setup
+ local options=(
+ --cli='qpdf'
+ "$@"
+ BREW='qpdf'
+ )
+ setup-util "${options[@]}"
+)
+
+# fire if invoked standalone
+if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
+ setup_util_qpdf "$@"
+fi
diff --git a/commands/setup-util-trash b/commands/setup-util-trash
index 49db9a392..fec483a98 100755
--- a/commands/setup-util-trash
+++ b/commands/setup-util-trash
@@ -1,8 +1,11 @@
#!/usr/bin/env bash
+# brew/macos version
# https://github.com/ali-rantakari/trash
# only provides [trash] binary
+# debian/ubuntu version
+# https://github.com/andreafrancia/trash-cli
# https://packages.debian.org/sid/amd64/trash-cli/filelist
# /usr/bin/trash
# /usr/bin/trash-empty
diff --git a/commands/sparse-vault b/commands/sparse-vault
index 872991bff..9c6c7bf92 100755
--- a/commands/sparse-vault
+++ b/commands/sparse-vault
@@ -115,15 +115,15 @@ function sparse_vault() (
function act_mount {
eval-helper --quiet \
- --pending="$(echo-style --bold="Compacting...")" \
- --success="$(echo-style --success="Compacted.")" \
- --failure="$(echo-style --error="Failed to compact.")" \
+ --pending="$(echo-style --bold='Compacting...')" \
+ --success="$(echo-style --success='Compacted.')" \
+ --failure="$(echo-style --error='Failed to compact.')" \
-- hdiutil compact "$option_path"
eval-helper --quiet \
- --pending="$(echo-style --bold="Mounting...")" \
- --success="$(echo-style --success="Mounted.")" \
- --failure="$(echo-style --error="Failed to mount.")" \
+ --pending="$(echo-style --bold='Mounting...')" \
+ --success="$(echo-style --success='Mounted.')" \
+ --failure="$(echo-style --error='Failed to mount.')" \
-- hdiutil mount "$option_path"
}
@@ -151,23 +151,23 @@ function sparse_vault() (
fi
eval-helper --quiet \
- --pending="$(echo-style --bold="Creating...")" \
- --success="$(echo-style --success="Created.")" \
- --failure="$(echo-style --error="Failed to create.")" \
+ --pending="$(echo-style --bold='Creating...')" \
+ --success="$(echo-style --success='Created.')" \
+ --failure="$(echo-style --error='Failed to create.')" \
-- hdiutil create "${args[@]}" "$option_path"
eval-helper --quiet \
--pending="$(echo-style --bold="Mounting...")" \
- --success="$(echo-style --success="Mounted.")" \
- --failure="$(echo-style --error="Failed to mount.")" \
+ --success="$(echo-style --success='Mounted.')" \
+ --failure="$(echo-style --error='Failed to mount.')" \
-- hdiutil mount "$option_path"
}
function act_unmount {
eval-helper --quiet \
--pending="$(echo-style --bold="Unmounting...")" \
- --success="$(echo-style --success="Unmount.")" \
- --failure="$(echo-style --error="Failed to unmount.")" \
+ --success="$(echo-style --success='Unmount.')" \
+ --failure="$(echo-style --error='Failed to unmount.')" \
-- hdiutil unmount "$option_path"
}
@@ -177,7 +177,7 @@ function sparse_vault() (
if [[ "$(type -t "act_$action")" == 'function' ]]; then
"act_$action"
else
- echo-style --stderr --error1="Action not yet implemented: " --code-error1="$action"
+ echo-style --stderr --error1='Action not yet implemented: ' --code-error1="$action"
return 78 # ENOSYS 78 Function not implemented
fi
)
diff --git a/commands/sudo-helper b/commands/sudo-helper
index 167e4268f..22a8d085b 100755
--- a/commands/sudo-helper
+++ b/commands/sudo-helper
@@ -27,6 +27,8 @@ function sudo_helper() (
specify a user to run the command as
--group=
specify a group to run the command as
+ --no-sudo | --sudo=no
+ If specified, and no nor is provided, then sudo will not be used, and the command will be run normally.
--inherit
if enabled, inherit environment variables include PATH.
@@ -39,7 +41,7 @@ function sudo_helper() (
if enabled, [eval-helper] will be used to confirm the execution of the command
--local
- update sudo configuration to enable access to /usr/local variables
+ update sudo configuration to enable access to /usr/local paths
EOF
if [[ $# -ne 0 ]]; then
@@ -50,7 +52,7 @@ function sudo_helper() (
# process
# option_quiet='no' is an important default to ensure our call to eval-helper can still be interpolated
- local item option_cmd=() option_quiet='no' option_reason='' option_user='' option_group='' option_confirm='no' option_wrap='no' option_inherit='no' option_local=''
+ local item option_cmd=() option_quiet='no' option_reason='' option_user='' option_group='' option_sudo='yes' option_confirm='no' option_wrap='no' option_inherit='no' option_local=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
@@ -65,6 +67,9 @@ function sudo_helper() (
'--reason='*) option_reason="${item#*=}" ;;
'--user='*) option_user="${item#*=}" ;;
'--group='*) option_group="${item#*=}" ;;
+ '--no-sudo'* | '--sudo'*)
+ option_sudo="$(get-flag-value --affirmative --fallback="$option_sudo" -- "$item")"
+ ;;
'--no-inherit'* | '--inherit'*)
option_inherit="$(get-flag-value --affirmative --fallback="$option_inherit" -- "$item")"
;;
@@ -89,9 +94,6 @@ function sudo_helper() (
# local
if [[ -n $option_local ]]; then
- # dependencies
- setup-util-sd --quiet
-
# trim problematic paths
local system_paths sudoers_line cron_system_line cron_user_line ignore_args=(
# these are not needed for [dorothy run] to bootstrap itself
@@ -144,8 +146,11 @@ function sudo_helper() (
# -i, --login
# Run the shell specified by the target user's password database entry as a login shell.
- local run=() home=''
- if __command_exists -- sudo; then
+ local run=() home='' command_style='sudo'
+ if [[ $option_sudo == 'no' ]]; then
+ command_style=''
+ run+=("${option_cmd[@]}")
+ elif __command_exists -- sudo; then
run+=('sudo')
if [[ -n $option_user ]]; then
@@ -220,6 +225,7 @@ function sudo_helper() (
run+=("${option_cmd[@]}")
else
# sudo/doas does not exist, probably not needed
+ command_style=''
run+=("${option_cmd[@]}")
fi
@@ -228,7 +234,7 @@ function sudo_helper() (
# the main thing here though, is that any failure should be detected and cancel in the caller
# perhaps requiring --ppid=$$ to be passed to sudo-helper is the way to go, as we do for [confirm]
if [[ $option_wrap == 'yes' || $option_confirm == 'yes' || $option_quiet == 'yes' ]]; then
- eval-helper --command="$(echo-style --sudo="$(echo-escape-command -- "${option_cmd[@]}")")" --wrap="$option_wrap" --quiet="$option_quiet" --confirm="$option_confirm" -- "${run[@]}"
+ eval-helper --command="$(echo-style --"$command_style"="$(echo-escape-command -- "${option_cmd[@]}")")" --wrap="$option_wrap" --quiet="$option_quiet" --confirm="$option_confirm" -- "${run[@]}"
else
"${run[@]}" # eval
fi