Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'd like to search for man pages which contain ALL of the words 'foo', 'bar' and 'baz'.

If possible, I'd like to search through all text (not just name & description) of all man pages.

I'm guessing something like

man -K foo AND bar AND baz
share|improve this question
    
did my script work? u didn't give any feedback :) –  polym Jun 24 at 3:21

3 Answers 3

up vote 5 down vote accepted

I implemented a script that does exactly this.

if [ $# -eq 0 ]; then
  PATTERNS=(NAME AUTHOR EXAMPLES FILES)
else
  PATTERNS=( "$@" )
fi

[ ${#PATTERNS[@]} -lt 1 ] && echo "Needs at least 1 pattern to search for" && exit 1

for i in $(find /usr/share/man/ -type f); do
  TMPOUT=$(zgrep -l "${PATTERNS[0]}" "$i")
  [ -z "$TMPOUT" ] && continue

  for c in `seq 1 $((${#PATTERNS[@]}-1))`; do
    TMPOUT=$(echo "$TMPOUT" | xargs zgrep -l "${PATTERNS[$c]}")
    [ -z "$TMPOUT" ] && break
  done

  if [ ! -z "$TMPOUT" ]; then
    #echo "$TMPOUT" # Prints the whole path
    MANNAME="$(basename "$TMPOUT")"
    man "${MANNAME%%.*}"
  fi
done

Guess it was a waste of time :(

Edit: Seems like

man -K expr1 expr2 expr3

didnt work?

Edit: You can pass the scripts now your search terms via ./script foo bar

share|improve this answer
    
Looks like a script is the only way after all. –  Graeme Jun 15 at 16:30
2  
Strange but ^true^ - but it was fun to vote for a waste of time... –  mikeserv Jun 15 at 16:38
    
Using different arguments just does or, I only thought it was and because I didn't test it properly. –  Graeme Jun 15 at 16:41
    
Thanks very much for this –  Tomsai Jul 1 at 18:30

Not as complete as @polym's answer, but I was going to suggest something like

while IFS= read -rd $'\0' f; do 
  zgrep -qwm1 'foo' "$f" && \
  zgrep -qwm1 'bar' "$f" && \
  zgrep -qwm1 'baz' "$f" && \
  printf '%s\n' "$f"
done < <(find /usr/share/man -name '*.gz' -print0)

Note that I added a -w (word match) switch to the greps - which may not be what you want (do you want to include matches like foolish and nutbar?)

share|improve this answer
    
Very polite of you to ask. –  mikeserv Jun 15 at 17:33

A few thoughts on scripting this:

  • Using manpath to get the location(s) of the man pages. If I add /home/graeme/.cabal/bin to my PATH, manpath (and man) will find man pages in /home/graeme/.cabal/share/man.

  • Use man itself to decompress and format the pages before searching, this way you are just searching the man text itself and not any comments etc in the raw file. Using man will potentially deal with multiple formats.

  • Saving the formatted pages in a tempfile will avoid multiple decompressions and should speed things up significantly.

Here goes (with bash and GNU find):

#!/bin/bash

set -f; IFS=:
trap 'rm -f "$temp"' EXIT
temp=$(mktemp --tmpdir search_man.XXXXXXXXXX)

while IFS= read -rd '' file; do
  man "$file" >"$temp" 2>/dev/null

  unset fail
  for arg; do
    if ! grep -Fq -- "$arg" "$temp"; then
      fail=true
      break
    fi
  done

  if [ -z "$fail" ]; then
    file=${file##*/}
    printf '%s\n' "${file%.gz}"
  fi
done < <(find $(manpath) -type d ! -name 'man*' -prune -o -type f -print0)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.