# main function designed for quickly copying to another program
progressBar() {
Bar="" # Progress Bar / Volume level
Len=25 # Length of Progress Bar / Volume level
Div=4 # Divisor into Volume for # of blocks
Fill="▒" # Fill up to $Len
Arr=( "▉" "▎" "▌" "▊" ) # UTF-8 left blocks: 7/8, 1/4, 1/2, 3/4
FullBlock=$((${1} / Div)) # Number of full blocks
PartBlock=$((${1} % Div)) # Size of partial block (array index)
while [[ $FullBlock -gt 0 ]]; do
Bar="$Bar${Arr[0]}" # Add 1 full block into Progress Bar
(( FullBlock-- )) # Decrement full blocks counter
done
# if remainder zero no partial block, else append character from array
if [[ $PartBlock -gt 0 ]]; then Bar="$Bar${Arr[$PartBlock]}"; fi
# Pad Progress Bar with fill character
while [[ "${#Bar}" -lt "$Len" ]]; do Bar="$Bar$Fill"; done
echo progress : "$1 $Bar"
exit 0 # Remove this line when copying into program
} # progressBar
Main () {
tput civis # Turn off cursor
for ((i=0; i<=100; i++)); do
CurrLevel=$(progressBar "$i") # Generate progress bar 0 to 100
echo -ne "$CurrLevel"\\r # Reprint overtop same line
sleep .04
done
echo -e \\n # Advance line to keep last progress
echo "$0 Done"
tput cnorm # Turn cursor back on
} # main
Main "$@"
since fdOpt is a single string (containing multiple arguments), Bash treats it as one single argument when passed to fd. This leads to the following issues:
--exclude '*.png' is treated as one single argument, rather than two separate ones: --exclude and '*.png';
As a result, fd cannot correctly interpret the glob pattern and treats it as a literal string;
Therefore, --exclude '*.png' does not actually exclude anything.
recommend using arrays to store multiple arguments and then pass them to the command.
# array
local -a fdArgs=(--type f --hidden --follow --unrestricted --ignore-file "${HOME}/.fdignore")
local ignores=(
'*.pem' '*.p12'
'*.png' '*.jpg' '*.jpeg' '*.gif' '*.svg'
'*.zip' '*.tar' '*.gz' '*.bz2' '*.xz' '*.7z' '*.rar'
'Music' '.target_book' '_book' 'OneDrive*'
)
for pattern in "${ignores[@]}"; do fdArgs+=(--exclude "${pattern}"); done
fdArgs+=(--exec-batch ls -t)
# array call
# +------------+
fd . "${fdArgs[@]}" | fzf ${foption} --bind="enter:become(${VIM} {+})"
details:
FORM
WORKS?
REASON
fd . ${fdOpt}
❌ No
${fdOpt} is a single string; arguments are not properly split
eval "fd . ${fdOpt}"
✅ Yes
Bash re-splits the command string before execution, but it’s risky
fd . "${fdArgs[@]}"
✅✅ Yes (Recommended)
Uses an argument array — most recommended, safe, and clean
METHOD
ARGUMENT PARSING
SAFETY
WILDCARD EXPANSION
RECOMMENDED USE CASE
$cmd
❌ Incorrect, treated as a single command
❌ Low
❌ No
Avoid using
eval "$cmd"
✅ Correctly splits arguments
⚠️ Low
✅ Yes
Quick testing or executing ad-hoc command strings
"${cmd[@]}"
✅ Correct and safe argument passing
✅ High
❌ No (no expansion)
Recommended for building command argument lists programmatically
$ ls
bar.bak bar.txt demo.sh foo.log foo.txt
$ bash demo.sh
→ Running: echo Listing *.txt with excludes: --exclude '*.log' --exclude '*.bak'
Listing bar.txt foo.txt with excludes: --exclude '*.log' --exclude '*.bak'
# +-------------+
# *.txt got expanded
→ Running with eval: echo Listing *.txt with excludes: --exclude '*.log' --exclude '*.bak'
Listing bar.txt foo.txt with excludes: --exclude *.log --exclude *.bak
# +-------------+
# *.txt got expanded
→ Running with array: echo Listing *.txt with excludes: --exclude *.log --exclude *.bak
Listing *.txt with excludes: --exclude *.log --exclude *.bak
$ cat -c demo.sh
#!/usr/bin/env bash
set -euo pipefail
function plainString() {
local cmd="echo Listing *.txt with excludes: --exclude '*.log' --exclude '*.bak'"
echo "→ Running: $cmd"
$cmd
}
function evalString() {
local cmd="echo Listing *.txt with excludes: --exclude '*.log' --exclude '*.bak'"
echo "→ Running with eval: $cmd"
eval "$cmd"
}
function arrayCall() {
local -a cmd=("echo" "Listing" "*.txt" "with" "excludes:" "--exclude" "*.log" "--exclude" "*.bak")
echo "→ Running with array: ${cmd[*]}"
"${cmd[@]}"
}
plainString
echo ''
evalString
echo ''
arrayCall
# vim:tabstop=2:softtabstop=2:shiftwidth=2:expandtab:filetype=sh:
wildcard expansion
METHOD
WILDCARD EXPANDED?
EXPLANATION
eval "echo *.txt"
✅ Yes
Shell expands the wildcard during evaluation
eval "echo '*.txt'"
❌ No
'*.txt' is a quoted string literal, not subject to expansion
"${arr[@]}"
❌ No
Arguments are passed as literal strings, no globbing applied
[!NOTEthinking:]
I got a issue with/without eval commands like: