-1

We have a git repo with a ton of projects and each project has an OWNERS file with one line like 'teams/search' with no quotes. I would like to somehow find all those files and create an array of tuples where the tuple is [filename, filecontents].

I can find all files with

find java -name "OWNERS" 

just fine or I can cat the contents like so

find java -name "OWNERS" | cat

How can I create the array though? The next step after that is looping over the array(I think I know how to do this though my bash is rusty) and I can create symlinks by cd to the team directory and ln -s {full file path}

0

2 Answers 2

2

bash data structures are not sophisticated enough to create an array of tuples. You can create an array of strings, or an associative array.

I'm assuming there are no newlines in the pathnames of the OWNERS files.

# an array of OWNERS filenames
mapfile -t owner_files < <(find java -name OWNERS)

# an associative array mapping the filename to the contents
declare -A owner_file_contents
for file in "${owner_files[@]}"; do
    owner_file_contents["$file"]=$(<"file")
done

# inspect the associative array
declare -p owner_file_contents

Bash is very sensitive to filenames with spaces in the name, so you need to quote all the variables.

Some notes:

  • mapfile -t ary < <(some command) -- runs some command in a subshell and read the output into an array, one line per element.

    • This cannot be done with some command | mapfile -t ary because bash runs pipeline commands in separate subshells, which means the array would be created in a subshell, therefore the array will disappear when the subshell exits.
    • refs: mapfile command, 3.5.6 Process Substitution
  • $(<file) is a builtin way to do $(cat file) without having to invoke an external command. Documented in 3.5.4 Command Substitution

1

Glenn's solution works great! I believe bash updated their data structures back in 2019? (The last I checked) to support mapfile..? It works great with arrays (and with tweaks works with maps as well).

Below is a sample pre-mapfile version that I put together quickly for dumping the content to the array.

array=( $(find find java -name "OWNERS") )

# loop over it
for i in ${array[@]}
do
 file_val= "${i}"
 file_contents="$(cat $i)"
 echo $i: $file_contents
done
2
  • Associative arrays and mapfile were added in bash version 4.0, more like 2012 Apr 19, 2021 at 15:01
  • 1
    Take care that there are no spaces around = for assignments. Apr 19, 2021 at 15:02

You must log in to answer this question.

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