I have a bash script that operates several similar find commands and reads the output into variables:
f_list=`find /foo -name bar | sort`
f_number=`find /foo -name bar | wc -l`
f_first=`find /foo -name bar | sort | head -n 1`
All this works as expected.
Assuming the "find" command to be expensive (time wise), is there a clever way of re-using one of the results for the others?
What I tried (and failed with) is:
f_list=`find /foo -name bar | sort`
f_number=`echo "$f_list" | wc -l`
f_first=`echo "$f_list" | head -n 1`
This doesn't work, but I hope it shows what I want to achieve.
It seems that putting the results into a variable spoils some format of the original output, which breaks stuff when sent again to the other commands.
Is there some clever way of achieving what I want?
EDIT
I created a fully working example you could recreate. In my working dir I have a folder "foo" with 3 files "bar1", "bar2", "bar3".
find_result=`find ./foo -type f -iname "bar*" | sort`
find_count1=`echo "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bar*" | wc -l`
find ./foo -type f -iname "bar*"
echo $find_count2
results in the expected
./foo/bar1
./foo/bar2
./foo/bar3
3
./foo/bar3
./foo/bar2
./foo/bar1
3
but when the result is empty (I modified the search criteria to find nothing)
find_result=`find ./foo -type f -iname "bor*" | sort`
find_count1=`echo "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bor*" | wc -l`
find ./foo -type f -iname "bor*"
echo $find_count2
the two results differ (notice the empty result line in front of the "1")
1
0
And thus I thought the culprint to be the extra line break in the echo command. Therefore I removed that (notice the "-n" in the second line):
find_result=`find ./foo -type f -iname "bor*" | sort`
find_count1=`echo -n "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bor*" | wc -l`
find ./foo -type f -iname "bor*"
echo $find_count2
which solves the problem for empty results
0
0
but now when there are results, the "wc -l" counts the wrong way so
find_result=`find ./foo -type f -iname "bar*" | sort`
find_count1=`echo -n "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bar*" | wc -l`
find ./foo -type f -iname "bar*"
echo $find_count2
yields in
./foo/bar1
./foo/bar2
./foo/bar3
2
./foo/bar3
./foo/bar2
./foo/bar1
3
So the problem is one line break that I thought must have an easy resolution to avoid being different between empty and non-empty find results. I have the feeling of missing something very simple.
Use an array to store the null
delimited list returned by find -print0 | sort -z
:
#!/usr/bin/env bash
# map null delimited output of command-group into the f_list array
mapfile -t f_list < <(find /foo -name bar -print0 | sort --zero-terminated)
# Number of entries in the f_list array
f_number=${#f_list[@]}
# First entry of the f_list array
f_first=${f_list[0]}