I want to create a list of filenames - that might have some filenames with spaces within.
This list shall be filtered in bash (not with 'find' itself - or alike).
The final list has to be processed somehow.
I can't make it work - unless using associative array.
Here's my solution.
test directory:
> find $HOME/test-dir/
/home/frank/test-dir/
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
script #1 (works):
> cat test2.sh
#!/bin/bash
mapfile -t Data < <(find $HOME/test-dir/ -type f)
for Key in ${!Data[@]}
do
echo "$Key -> ${Data[$Key]}"
done
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
Note: The process substitution at the end of the script shall enable to handle the values only within the loop w/o need to know it's stored in an associative array (for old code).
output:
> ./test2.sh
0 -> /home/frank/test-dir/FileA
1 -> /home/frank/test-dir/File D
2 -> /home/frank/test-dir/FileC
3 -> /home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileB
Any attempt to use a pure array fails for the "File D". I can populate the array, but traversing or trying to remove an element breaks it again:
script #2 (does not work):
> cat test2.sh
#!/bin/bash
OLDIFS="$IFS"
IFS=$'\n'
readarray -t Data < <(find $HOME/test-dir/ -type f)
IFS="$OLDIFS" # works only if i drop this
for Value in ${Data[@]}
do
echo "$Value"
done
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
for Value in ${Data[@]}
do
echo "$Value"
done
output:
> ./test2.sh
/home/frank/test-dir/FileA
/home/frank/test-dir/File
D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File
D
/home/frank/test-dir/FileB
Interestingly, removing the restoration of the IFS (see commented line above) results in
output:
> ./test2.sh
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileB
But i want to localize the setting of IFS to not interfere with old code, that relies on different IFS value.
What's the way to make it work with pure array (not associative array)?
Addendum:
This also works:
> cat test2b.sh
#!/bin/bash
readarray -t Data < <(find $HOME/test-dir/ -type f)
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
But kind of strange to have to go like this. I used process substitution for my solution with associative array. But that was, because i introduced key->value myself and had to get back to the values only. Required to do so for the pure array feels strange.