Parse find input into array

I need help parsing the output of find into an array. I need to search 3 directories and find all files older than 31 days old. This is what I have so far.

TIME=" -maxdepth 1 -mtime +31"
DIR1="/dir1/"
DIR2="/dir2/"
DIR3="/dir3/"

FIND_DIR1=$(find ${DIR1}${TIME})
FIND_DIR3=$(find ${DIR2}${TIME})
FIND_DIR3=$(find ${DIR3}${TIME})

IFS=' ' read -a array <<< "$FIND_DIR1"
for element in "${array[@]}"
do
    echo "$element"
done

When I echo the FIND_DIR variables, it prints out..
/dir1/file1 /dir1/file2 separated by what I'm assuming is either white space or a tab.

The issue I'm having is when I try to put the output of the find into an array, array index 0 has both /dir1/file1 and /dir1/file2

I need array index 0 to be file 1 and array index 1 to be file 2.

The above code will output /dir1/file1 for both array index 0 and array[@], it prints nothing when asked to print array index 1.

Thank you in advance.

try in script:

array=($($FIND_DIR1))
for element in "${array[@]}"
do
    echo "$element"
done

It says /dir1/file1: Permission denied, I put sudo before it as well.

Another approach in BASH:

#!/bin/bash

DIR="/dir1/"
idx=0

FIND_DIR=$( find ${DIR} -type f )

for file in $FIND_DIR
do
  array[$idx]="$file"
  idx=$(( idx + 1 ))
done

end_idx="${#array[@]}"

for idx in $( seq 1 $end_idx )
do
  echo ${array[idx]}
done

You could do something like this (using non-standard shell syntax):

bash-4.2$ mkdir dir{1..3}
bash-4.2$ touch -t 201211010000 dir{1..3}/file{1,2}
bash-4.2$ ls -l dir{1..3}
dir1:
total 0
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file1
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file2

dir2:
total 0
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file1
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file2

dir3:
total 0
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file1
-rw-r--r-- 1 sysadmin None 0 Nov  1 00:00 file2

Given the directory structure and the files above, the following code:

_find_opts=( 
  -maxdepth 1 
  -mtime +31
  )
_dirs=( 
  dir1 
  dir2 
  dir3 
  )

for d in "${_dirs[@]}"; do
  eval "__find_$d=( $( find "$d" "${_find_opts[@]}" ) )"
done

for fd in ${!__find_*}; do
  eval "_files=( "\${$fd[@]}" )"
  printf 'files in %s:\n' "$fd"  
  for f in "${_files[@]}"; do
    printf '%s\n' "$f"
  done
done

Produces:

files in __find_dir1:
dir1/file1
dir1/file2
files in __find_dir2:
dir2/file1
dir2/file2
files in __find_dir3:
dir3/file1
dir3/file2

This is only for illustration! Most probably the eval ... parts could be avoided ...
I don't believe you really need a separate structures/arrays. If you tell us what you actually need to do,
we could give a more appropriate solution.

@rdrtx1
I changed the permissions and got it run but it produces the incorrect output, if it finds one file it prints one newline, if two files are found it prints two newlines etc. Also I fail to see where you are taking the individual files and putting them into an array.

@bipinajith
I tried something like this earlier and it did not work either. When I do this is does not split up my string either. Array index one still prints out the full string, I do not see where this splits the string up either.

@radoulov
I do not fully understand your code because I am very new to bash, I just need to know exactly how to split a string from find into an array.

What I am trying to do:
-find files older than 31 days from multiple directories
-store those multiple files into an array based on which directory they are from
-iterate through those arrays and ask the user if there are any files they want to keep
-deleted all the files that the user does not want kept

I am stuck on the 2nd step though, if my find result produces one hit, everything works fine, but if more than one item is found, then both of those items are stored as one index. I have tried many options and the closest I have come is storing one of the files as array index one, but array index two remains empty, leaving out the other files.

I do not understand how to split a string at whitespace and then get it into an array.

Is there a pipe I could use for this?

I do not understand how to split a string at whitespace and then get it into an array.

With bash >= 4, if I recall correctly:

$ _string='a b c'
$ read -a _array <<< "$s"
$ declare -p _array
declare -a _array='([0]="a" [1]="b" [2]="c")'

Otherwise (zsh, bash, ksh93):

_array=( $_string )

If you need standard code, you can use positional parameters (you may need to save the existing ones first):

$ set -- $_string
$ # now you have all elements in "$@", single elements
$ # could be accessed using $1, $2 ... etc. 
  1. You can find them with a single command: find dir1 dir2 ... -mtime ... .
  2. Why do you think, you need to do this?
  3. You could iterate through the files using a while read loop and do whatever you need to do inside the loop:
find ... | while IFS= read -r; do #filename is in $REPLY ...

I got it working, I was complicating things WAY too much. I think I made an error earlier on while testing it that led me to skip over the solution.

This does what I need.

j=1
for i in ${FIND_DIR1}
do
	array[j]=$i
	let j++
done

echo ${array[@]}

The for loop splits it at the white space. The error I kept running into was trying to force the IFS to split it, and trying to force split it other wise.

Thank you for the help it was much appreciated!

try (bash):

array=($(find . -type f))