Elegant way to construct a pipeline based on return value and not exit code?
Create a function that takes a command and returns true iff it has some output.
r() { local x=$("$@"); [ -n "$x" ] && echo "$x"; }
( ( r echo -n ) || echo 'nada' ) | cat # Prints 'nada'
( ( r echo -n foo ) || echo 'nada' ) | cat # Prints 'foo'
So for this use case it 'll work like this,
r apt-cache search hunspell-en-zz || r apt-cache search hunspell-en
As far as I know, there is no standard way to deal with those cases where the success of a command is determined by the presence of output. You can write workarounds, though.
For example, you can save the output of the command in a variable and then check if that variable is empty or not:
output="$(command)"
if [[ -n "${output}" ]]; then
# Code to execute if command succeded
else
# Code to execute if command failed
fi
I think this answers the question in a general way, but if we talk about apt-cache search
some solutions come to my mind.
I have a script which makes package management easier. Some of its functions are these:
search() {
local 'package' 'packages'
packages="$( apt-cache search '.*' | cut -d ' ' -f '1' | sort )"
for package; do
grep -F -i -e "${package}" <<< "${packages}"
done
}
search_all() {
local 'package'
for package; do
apt-cache search "${package}" | sort
done
}
search_description() {
local 'package' 'packages'
packages="$( apt-cache search '.*' | sort )"
for package; do
grep -F -i -e "${package}" <<< "${packages}"
done
}
search_names_only() {
local 'package'
for package; do
apt-cache search --names-only "${package}" | sort
done
}
These let you to do multiple searches in a single command. For example:
$ search hunspell-en-zz hunspell-en
hunspell-en-au
hunspell-en-ca
hunspell-en-gb
hunspell-en-med
hunspell-en-us
hunspell-en-za
Every function search the database in a different way, so the results may vary depending of wich function you use:
$ search gnome | wc -l
538
$ search_all gnome | wc -l
1322
$ search_description gnome | wc -l
822
$ search_names_only gnome | wc -l
550
I wouldn't call this elegant but I think it might do the job:
search_packages () {
local packages=($@)
local results=()
for package in "${packages[@]}"; do
results=($(apt-cache -n search "$package"))
if [[ "${#results[@]}" -eq 0 ]]; then
echo "$package not found."
elif [[ "${#results[@]}" -eq 1 ]]; then
do stuff with "$package"
else
echo "Warning! Found multiple packages for ${package}:"
printf '\t-> %s\n' "${results[@]}"
fi
done
}
I don't have a debian machine to test on unfortunately. I've included the -n
for "names-only" option of apt-cache
to try and limit the search results as it looks like you are mostly sure of what you are searching.
Can be run like:
$ search_packages hunspell-en-zz hunspell-en
$ my_packages=('hunspell-en-zz' 'hunspell-en')
$ search_packages "${my_packages[@]}"