# Parse find input into array

**URL:** <https://community.unix.com/t/parse-find-input-into-array/322075>\
**Category:** Shell Programming and Scripting\
**Created:** [January 2, 2013, 2:49pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075 "2013-01-02T14:49:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jrymer](https://community.unix.com/user_avatar/community.unix.com/jrymer/32/8152_2.png) [@jrymer](https://community.unix.com/u/jrymer)\
**Post date:** [January 2, 2013, 2:49pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/1 "2013-01-02T14:49:56Z")

</div>

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.

```nohighlight
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.

---

<div class="post-metadata">

**Author:** ![rdrtx1](https://community.unix.com/user_avatar/community.unix.com/rdrtx1/32/2721_2.png) [@rdrtx1](https://community.unix.com/u/rdrtx1)\
**Post date:** [January 2, 2013, 4:10pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/2 "2013-01-02T16:10:00Z")

</div>

try in script:

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

```

---

<div class="post-metadata">

**Author:** ![jrymer](https://community.unix.com/user_avatar/community.unix.com/jrymer/32/8152_2.png) [@jrymer](https://community.unix.com/u/jrymer)\
**Post date:** [January 2, 2013, 4:27pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/3 "2013-01-02T16:27:15Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Yoda](https://community.unix.com/user_avatar/community.unix.com/yoda/32/2498_2.png) [@Yoda](https://community.unix.com/u/Yoda)\
**Post date:** [January 2, 2013, 4:36pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/4 "2013-01-02T16:36:36Z")

</div>

Another approach in BASH:

```nohighlight
#!/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

```

---

<div class="post-metadata">

**Author:** ![radoulov](https://community.unix.com/user_avatar/community.unix.com/radoulov/32/489_2.png) [@radoulov](https://community.unix.com/u/radoulov)\
**Post date:** [January 2, 2013, 4:46pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/5 "2013-01-02T16:46:56Z")

</div>

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

```nohighlight
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:

```nohighlight
_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:

```nohighlight
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.

---

<div class="post-metadata">

**Author:** ![jrymer](https://community.unix.com/user_avatar/community.unix.com/jrymer/32/8152_2.png) [@jrymer](https://community.unix.com/u/jrymer)\
**Post date:** [January 3, 2013, 10:16am UTC](https://community.unix.com/t/parse-find-input-into-array/322075/6 "2013-01-03T10:16:12Z")

</div>

@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.

> [@](#):
>
> If you tell us what you actually need to do,  
> we could give a more appropriate solution.

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?

---

<div class="post-metadata">

**Author:** ![radoulov](https://community.unix.com/user_avatar/community.unix.com/radoulov/32/489_2.png) [@radoulov](https://community.unix.com/u/radoulov)\
**Post date:** [January 3, 2013, 11:15am UTC](https://community.unix.com/t/parse-find-input-into-array/322075/7 "2013-01-03T11:15:52Z")

</div>

```plaintext
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:

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

```

Otherwise (zsh, bash, ksh93):

```plaintext
_array=( $_string )

```

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

```plaintext
$ set -- $_string
$ # now you have all elements in "$@", single elements
$ # could be accessed using $1, $2 ... etc. 

```

> [@](#):
>
> 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

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:

```plaintext
find ... | while IFS= read -r; do #filename is in $REPLY ...

```

---

<div class="post-metadata">

**Author:** ![jrymer](https://community.unix.com/user_avatar/community.unix.com/jrymer/32/8152_2.png) [@jrymer](https://community.unix.com/u/jrymer)\
**Post date:** [January 3, 2013, 11:44am UTC](https://community.unix.com/t/parse-find-input-into-array/322075/8 "2013-01-03T11:44:02Z")

</div>

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.

```nohighlight
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!

---

<div class="post-metadata">

**Author:** ![rdrtx1](https://community.unix.com/user_avatar/community.unix.com/rdrtx1/32/2721_2.png) [@rdrtx1](https://community.unix.com/u/rdrtx1)\
**Post date:** [January 3, 2013, 12:05pm UTC](https://community.unix.com/t/parse-find-input-into-array/322075/9 "2013-01-03T12:05:27Z")

</div>

try (bash):

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

```
