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