1

I am using bash to get all of my directories with find . -maxdepth 1 -type d. I am then storing it in an array called selections. The issue is if a file has a space in it then i get some issues. When i try to sort the array, even when changing the delimiter. This is the original set up I tried:

selections=( $(find . -maxdepth 1 -type d) )

unset "selections[0]"; ## removes . as an option

readarray -t sorted_selections < <(IFS=$'\n'; sort <<<"${selections[*]}")
for ((i=0; i<${#sorted_selections[@]}; i++)); do
  sorted_selections[i]=${sorted_selections[i]:2}
done

Then when this failed I changing the delimiter to ./ being each result starts with ./, and then removed the code that removed the ./ from the element.

selections=( $(find . -maxdepth 1 -type d) )

unset "selections[0]"; ## removes . as an option

readarray -d ./ -t sorted_selections < <(IFS=$'\n'; sort <<<"${selections[*]}")
for ((i=0; i<${#sorted_selections[@]}; i++)); do
 # sorted_selections[i]="${sorted_selections[i]:2}"
done

How can I prevent the sorting from spiting elements for example: taking "New File" to "New" "File"?

2
  • It's not the sorting; the original selections=( $(find ...) ) did the split at any IFS char, which defaults to including space. If you set IFS=$'\n' before the first line it works, but is clumsy; see comment on answer Commented Jun 7 at 3:44
  • 1
    Bash pitfall number 1. Commented Jun 7 at 4:21

1 Answer 1

0

The solution was to use mapfile. This resolves the issue.

mapfile selections < <(find . -maxdepth 1 -type d) 
 unset "selections[0]"; ## removes . as an option
 readarray -t sorted_selections < <(IFS=$'\n'; sort <<<"${selections[*]}")
 for ((i=0; i<${#sorted_selections[@]}; i++)); do
   sorted_selections[i]=${sorted_selections[i]:2}
 done

for v in "${sorted_selections[@]}"; do if test "$v"; then var2+=("$v"); fi;
done
printf '%s\n' "${var2[@]}"

This did create some odd behavior in my bash script after implementing this but thats a different probelm.

Edit: I have found an even better soultion:

IFS=''
selections=( $(find . -maxdepth 1 -type d) )
unset IFS

readarray -t sorted_selections < <(IFS=$'\n'; sort <<<"${selections[*]}")
for ((i=0; i<${#sorted_selections[@]}; i++)); do
  sorted_selections[i]=${sorted_selections[i]:2}
done

for ((c=0; c<${#sorted_selections[@]}; c++)); do
sorted_selections[c]="\033[0;34m\033[40m${sorted_selections[c]}\033[0m";
done

unset "sorted_selections[0]"; ## removes . as an option

Like mentioned in the comments there isn't really much you can do with the return/next line character. There might be a way to handle it with

eval "$(
  find . -type f -exec bash -c '
    file_array=("$@")
    declare -p file_array
  ' -s '{}' +
)"

echo "--- outside find ---"
declare -p file_array

but why mess with something that works

3
  • 2
    Alternatively in bash just do shopt -s dotglob nullglob (dotglob only needed if you have or may have 'hidden' dirs and want them included) and optionally declare -a sorted_selections then for d in */;do sorted_selections+=( ${d%/} ); done. This enumerates the names for one level only in sorted order, excepting .. which you must add explicitly if you really want it, so you need only remove the extra slash. This has the theoretical advantage of working for dir-names that contain newline, but such names cause so many other problems no sensible person ever uses them. Commented Jun 7 at 3:45
  • That doesnt quite work. You lose the hidden files and it still treats "New File" as "New" "File". selections=( $(shopt -s dotglob nullglob && find . -maxdepth 1 -type d) ) unset "selections[0]"; declare -a sorted_selections for d in */;do sorted_selections+=( ${d%/} ); done Commented Jun 7 at 18:14
  • Sorry, I should have said sorted_selections+=( "${d%/}" ). dotglob should -- and on my system does -- include hidden directories other than . and ... But note I meant to do all two or three commands -- shopt [declare] for... -- in the toplevel shell, not in a subshell, and no find at all. Commented Jun 9 at 9:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .