0

I want to loop through a list of directories (a subset of the directories in a folder) and do operations with them. However, for some reason it is not working. Here is the code where I am just echoing all of them:

#!/bin/bash                                                                                                                                                                   
                                                                                                                                                                              
cd images                                                                                                                                                                     
array=$(ls -d *)                                                                                                                                                              
selection=(${array[@]:1:12})                                                                                                                                                  
cd ..                                                                                                                                                                         
                                                                                                                                                                              
for sub in ${selection[@]}                                                                                                                                                    
do                                                                                                                                                                            
    echo $sub                                                                                                                                                                 
    mkdir $HOME/Projects/PhD/0_project/fMRI/scans/temp/temp_$sub                                                                                                              
done    

The ouptut I get for the echo command is:

04
306
307
3

And the folders: temp_3, temp_04, temp_306, temp_307

HOWEVER, if I run each single line in bash in the termiinal (interactive mode, no script) I do get the correct output for the echo command:

306
307
308
309
310
311
312
314
317
318
323
324

And for the mkdir command: temp_306, temp_307... temp_324

Any idea about this strange and inconsistent behaviour? What am I missing?

Thanks for your help.

4
  • array=( */ ) is a much less buggy way to put folder names into an array. array=( "${array[@]%/}" ) to postprocess if you don't want the trailing slashes. Parsing ls is bad juju, and doing it badly defeats the whole point of using arrays in the first place (their ability to accurately store arbitrary strings). Though your current code isn't actually using arrays at all. Commented Jul 21, 2022 at 15:53
  • It's a good idea to run any shell script through shellcheck.net. In this case, I think it would've found the issue for you. Commented Jul 21, 2022 at 15:53
  • BTW, it's a good idea to make sure people know enough to understand how your code is supposed to work as part of the question (we can tell what working code does by reading it, but we can't tell what broken code was intended by its author to do without trying to read its author's mind; don't make us do that). What should the path entries in images look like? Commented Jul 21, 2022 at 15:59
  • Thanks. They are folders named with three digits ("304", "424", "306", etc.) Commented Jul 21, 2022 at 17:59

1 Answer 1

1

result of $(ls -d *) is a string.
you are slicing a string not an array.

remove :1:12.

#!/bin/bash

cd images || exit
array=(*/) # result is array of subdirectories with / on end of each
selection=("${array[@]%/}") # remove trailing slashes from that array.
selection_sliced=("${selection[@]:1:12}") # if you want to slice.
cd .. || exit

for sub in "${selection_sliced[@]}"
do
    echo "$sub"
    mkdir "$HOME/Projects/PhD/0_project/fMRI/scans/temp/temp_$sub"
done
Sign up to request clarification or add additional context in comments.

7 Comments

But what if I want to select only a subset of the elements of that array to feed into the for loop?
@Carlos_567 just slice the variable selection. selection is an array. i edited post.
selection=( ${array[@]} ) is buggy; see BashPitfalls #50. And for sub in ${array[@]} acts exactly like for sub in ${array[*]}; do get proper array behavior it needs to be for sub in "${array[@]}" with the quotes.
Similarly this answer has a whole lot of quoting bugs; consider running it through shellcheck.net -- and see ParsingLs.
Much better as amended. I'm not sure if it's what the OP needs, but that's because their question is vague, not because of anything wrong with this answer. I did add a few minor cleanups -- cd should always handle errors so you don't run your mkdirs in the wrong directory should they fail -- and correct some comments.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.