Reputation: 47
I am attempting to write a script that tried to use globstar
expressions to execute a command (for example ls
)
#!/usr/bin/env bash
shopt -s globstar nullglob
DISCOVERED_EXTENSIONS=$(find . -type f -name '*.*' | sed 's|.*\.||' | sort -u | tr '\n' ' ' | sed "s| | ./\**/*.|g" | rev | cut -c9- | rev | echo "./**/*.$(</dev/stdin)")
IFS=$'\n'; set -f
for f in $(echo $DISCOVERED_EXTENSIONS | tr ' ' '\n'); do
ls $f;
done
unset IFS; set +f
shopt -u globstar nullglob
The script output is:
ls: ./**/*.jpg: No such file or directory
ls: ./**/*.mp4: No such file or directory
It is passing ls "./**/*.avi"
instead of ls ./**/*.avi
(no variable expansion). I attempted to use eval, envsubst and even used a custom expand
function, to no avail
The result of echo "$DISCOVERED_EXTENSIONS"
is:
./**/*.jpg ./**/*.mp4
What changes can be recommended so that value of $f
is the result of glob expansion and not the expression itself?
EDIT: I'm keeping the question up as I have resolved my problem by not using globstar
at all which solves my immediate problem but doesn't solve the question.
As pynexj points out, the set -f
un-does shopt -s globstar nullglob
so that makes the script I've written as non-functional 'cause removing set -f
breaks this script
Upvotes: 2
Views: 893
Reputation: 141930
$f is the result of glob expansion
The result of glob expansion is a list of arguments. It could be saved in an array. Saving it is just calling a subshell and transfering data.
mapfile -t -d '' arr < <(bash -c 'printf "%s\0" '"$f")
ls "${arr[@]}"
Notes:
for i in $(....)
. Use a while IFS= read -r
loop. Bashfaq how to read a stream line by line.DISCOVERED_EXTENSIONS
long line, but I would find . -maxdepth 1 -type f -name '*.*' -exec bash -c 'printf "%s\n" "${0##*.}"' {} \; | sort -u
.find . -maxdepth 1 -type f -name '*.*' -exec bash -c 'printf "%s\n" "${0##*.}"' {} \; | sort -u | while IFS= read -r ext; do find . -type f -name "*.$ext" | xargs -d '\n' ls; done
Upvotes: 1