Home > Enterprise >  Linux find, get output to a variable before and after -exec respectively
Linux find, get output to a variable before and after -exec respectively

Time:03-05

In a shell script (sh) I want to find an executable file, retain its run output in a variable and its path in another variable.

Say I want to find all installed OpenCV versions, then retain the major in a variable and the location of the file in another variable.

list=$(find / -type f -name opencv_version -exec {} \; 2>/dev/null | sort -u | cut -c-1); printf "%c;" $list

will return say 3;4; but I also want the opencv_version file location for version 3 and 4 respectively. For that I would need to store the output of the first part find / -type f -name opencv_version in another variable, before running -exec {} \;

Can I do these two ops in a one liner?

CodePudding user response:

Use -print and -exec, and put the output processing in a shell

For example, on my mac with GNU awk installed via homebrew:

find -L /usr -name awk -type f -executable \
             -print \
             -exec sh -c '"$1" --version | head -n 1' sh {} \;  2>/dev/null

outputs

/usr/bin/awk
awk version 20200816
/usr/local/bin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/var/homebrew/linked/gawk/bin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/var/homebrew/linked/gawk/libexec/gnubin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/opt/gawk/bin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/opt/gawk/libexec/gnubin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/Cellar/gawk/5.1.1/bin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
/usr/local/Cellar/gawk/5.1.1/libexec/gnubin/awk
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)

Those lines can be process in pairs.

CodePudding user response:

Suggesting to read list of sorted files into an array.

Than print each array elements followed by with its execution result:

readarray -t fileNamesArr < <(find / -type f -name opencv_version -executable 2>/dev/null | sort -u)
for aFileName in ${fileNamesArr[@]}; do printf "%s; %c\n" $aFileName $(aFileName); done

Additional suggestion, use locate command if possible. It is faster and simpler. If you have frequently udated files lists with updatedb.

Testing this solution

Reading sorted list of all service files in machine. Than for each serviceFile print its path, and its chars count.

readarray -t servicesArr < <(locate "*.service"|sort -u)
for serviceFile in ${servicesArr[@]}; do 
  printf "%s; %s\n" "$serviceFile" $(cat "$serviceFile"| wc -m );
done
  • Related