HTF
HTF

Reputation: 7260

BASH: append to array

Please be aware that this is just a pseudo code to illustrate the problem:

Directory structure:

# tree
.
├── dir1
│   ├── d1_file1
│   ├── d1_file2
│   └── d1_file3
└── dir2
    ├── d2_file1
    ├── d2_file2
    └── d2_file3

2 directories, 6 files

Script:

#!/bin/bash

list=(
dir1
dir2
)

for dir in ${list[@]}; do
    ls -1 ./tmp/${dir} | while read -a file; do
    files+=(${file})
    echo "${dir} has ${#files[@]} files(s)"
    echo "${dir} files: ${files[@]}"
    done
done

Current output:

# bash tmp.sh 
dir1 has 1 files(s)
dir1 files: d1_file1
dir1 has 2 files(s)
dir1 files: d1_file1 d1_file2
dir1 has 3 files(s)
dir1 files: d1_file1 d1_file2 d1_file3
dir2 has 1 files(s)
dir2 files: d2_file1
dir2 has 2 files(s)
dir2 files: d2_file1 d2_file2
dir2 has 3 files(s)
dir2 files: d2_file1 d2_file2 d2_file3

Desired outcome:

# bash tmp.sh
dir1 has 3 files(s)
dir1 files: d1_file1 d1_file2 d1_file3
dir2 has 3 files(s)
dir2 files: d2_file1 d2_file2 d2_file3

Basically I would like to build a separate array for each item in the for loop that stores values from the ls command.

Upvotes: 0

Views: 246

Answers (2)

mklement0
mklement0

Reputation: 437833

You can simply use pathname expansion (globbing) to capture all the files in your subdirectories:

list=(
 dir1
 dir2
)

for dir in "${list[@]}"; do
    files=( ./tmp/"${dir}"/* )  # collect all matches in array
    echo "${dir} has ${#files[@]} files(s)"
    echo "${dir} files: ${files[@]}"
done

Note how I've double-quoted ${list[@]} and ${dir} to protect their values from shell expansions.
By contrast, the * must be unquoted so as to trigger pathname expansion.

Upvotes: 1

Tom Fenech
Tom Fenech

Reputation: 74615

In order to only output the count once per directory, you need to move the printing out of the while read loop. However, I would suggest removing it entirely. Try something like this:

#!/bin/bash

list=(
dir1
dir2
)

for dir in "${list[@]}"; do
    files=( ./tmp/"$dir"/* )
    echo "${dir} has ${#files[@]} files(s)"
    echo "${dir} files: ${files[@]}"
done

This uses a glob to populate the files array with the contents of each directory.

In general, parsing ls should be avoided.

Upvotes: 2

Related Questions