6

we want to build 6 mount point folders as example

/data/sdb
/data/sdc
/data/sdd
/data/sde
/data/sdf
/data/sdg

so we wrote this simple bash script using array

folder_mount_point_list="sdb sdc sdd sde sdf sdg"

folderArray=( $folder_mount_point_list )

counter=0
for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6
do
folder_name=${folderArray[counter]}
mkdir /data/$folder_name
let counter=$counter+1
done

now we want to change the code without counter and let=$counter=counter+1

is it possible to shift each loop the array in order to get the next array value?

as something like

${folderArray[++]}
  • 1
    what's for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6 for as it's not being used within loop body? – RomanPerekhrest Dec 31 '17 at 13:37
  • 1
    ... and what is the point of using a counter ? Why don't you simply run for i in "your_list_goes_here"; do mkdir /data/"$i"; done ? – don_crissti Dec 31 '17 at 13:38
5

A general remark. It does not make sense to define an array like this:

folder_mount_point_list="sdb sdc sdd sde sdf sdg"
folderArray=( $folder_mount_point_list )

You would do this instead:

folderArray=(sdb sdc sdd sde sdf sdg)

Now to your question:

set -- sdb sdc sdd sde sdf sdg
for folder_name; do
    mkdir "/data/$folder_name"
done

or

set -- sdb sdc sdd sde sdf sdg
while [ $# -gt 0 ]; do
    mkdir "/data/$1"
    shift
done
  • can we do the set for variable as set -- $list_of_folders ( while list_of_folders="sdb sdc sdd sde" – yael Dec 31 '17 at 13:48
  • @yael Yes, you can use set -- $list_of_folders but again: String variables are not the way to go: set -- "${folders[@]}" – Hauke Laging Dec 31 '17 at 14:02
  • why are you even using set -- ....? that hack is only needed in shells that don't support arrays - there's no need for it in a shell that does supports arrays. for folder_name in "${folderArray[@]}"; do ... ; done is all that's needed. – cas Dec 31 '17 at 14:12
  • just one question , is there any choice to do something like - ${folderArray[++]} – yael Dec 31 '17 at 14:16
  • @cas that's what I have in my answer. I don't get this set approach either. – PesaThe Dec 31 '17 at 20:12
9

To answer the question in the title, you can "shift" an array with the substring/subarray notation. (shift itself works with just the positional parameters.)

$ a=(a b c d e)
$ a=("${a[@]:1}")
$ echo "${a[@]}"
b c d e

Similarly, to 'pop' the last item off the array: a=("${a[@]:0:${#a[@]} - 1}" ) or unset "a[${#a[@]}-1]"

So if you wanted to, you could do this:

a=(foo bar doo)
b=(123 456 789)
while [ "${#a[@]}" -gt 0 ] ; do
    echo "$a $b"
    a=("${a[@]:1}")
    b=("${b[@]:1}")
done

But it trashes the arrays, so just indexing as usual might be better. Or maybe use an associative array instead:

declare -A arr=([foo]=123 [bar]=456 [doo]=789)
3

You don't need any loop for that:

folderArray=(sdb sdc sdd sde sdf sdg)
IFS=,
eval mkdir /data/{"${folderArray[*]}"}

The trick is that if an array is double-quoted with subscript * ("${array[*]}") it expands to a single word with the value of each array element separated by the first character of the IFS variable. After that we use brace expansion mechanism to attach /data/ to each array member and evaluate the whole thing.

  • Why so complicated? cd /data ; mkdir "${folderArray[@]}" I have done the same before but I would not in a case like this. But +1 for the advanced approach. – Hauke Laging Dec 31 '17 at 14:03
  • @HaukeLaging Yes, that would be simpler in case of mkdir command. And and even array is not needed, just cd /data; mkdir abc def as normal person would do. But could not be as simple for other tasks, so it is good to know how to quickly attach a string to each array element without a loop. – jimmij Dec 31 '17 at 14:11
  • just one question , is there any choice to do something like - ${folderArray[++]} – yael Dec 31 '17 at 14:16
  • 1
    @yael You can do something like echo "${folderArray[((counter++))]}" if you really like this approach. Stuff inside (()) is evaluated as math (notice lack of $ in front of counter). – jimmij Dec 31 '17 at 14:22
  • and when you start writing shell code like that, you realise that putting a little time into learning perl or python would be a good idea. i.e. just because you can do something with bash, doesn't mean you should. – cas Dec 31 '17 at 14:27
3

You can simply loop over all values, no shifting needed:

folderArray=(sdb sdc sdd sde sdf sdg)

for folder in "${folderArray[@]}"; do
    mkdir "/data/$folder"
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.