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.
#!/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.
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.