39

I finally got fed up when wanting to read about bash's read and it's -s option with man bash. I found the right spot eventually (around line 4500), but it was a frustrating as usual, since both /read and even /\s-s\s searches have way too many matches.

So, the question is: How can I read long man pages efficiently, or get same information in other ways, locally? As a specific example, how to reach the relevant documentation after seeing read -s pwd in a shell script? A good answer could be a shell script snippet, or hint about some tool and how it is used, or something else entirely, as long as it helps in finding the right spot to read.

Note: I'm not tagging with because I want the question to be about man page reading in general, even though that quite possibly is the most commonly encountered humongous man page.

hyde
  • 1,288
  • 1
  • 13
  • 20
  • I'm not putting this as an answer because it may be outside your requirements but: when I need to read a long man page I use a little script i leave on my upper panel. http://www.yuugian.com/demo/gkman.txt Share and enjoy – Yuugian Oct 15 '13 at 13:01
  • I'm not putting this as an answer either ;) because it's indeed about bash itself: just like you, I too mostly need the SHELL BUILTINS part of the manual, which is at about line 3500. So knowing this, the next time I would just say man bash and then go down 66 percent, by typing 66%, then a few times PgDn and I'm there. Though I chose 66 because it can be memorized as "Route 66", it is actually a little more than that, albeit not so easy to memorize unless it is the beginning of your phone #, etc. :) At least the "Route 66" is universal and known worldwide. – syntaxerror Dec 14 '14 at 22:45

9 Answers9

38

For quickly getting help on a Bash builtin, use help:

help read

is what you want.

For man-page-like formatting, use

help -m read

or, even better,

help -m read | less

If you still insist on looking for it in the man page, I find what quickly gets me to a command's explanation is

/^\s*read [[]

This works because when a command is first explained, its name is indented slightly from the start of the line. In the particular case of read, this takes a little browsing before you get to the actual read documentation because (for obvious reasons) the word "read" is repeated a lot throughout the man page. The [[] means to match a [ which usually precedes optional parameters. (I usually leave out /^\s* and simply do /<built-in command> [[])

Another alternative

If you don't mind the format change, you can convert your man page to a DVI or PDF file:

man -T dvi bash >bash.dvi

or

man -T ps bash | ps2pdf - bash.pdf # Requires the Ghostscript suite for ps2pdf

Of course, given a DVI or PDF document, you can then do a text search easily.

thecarpy
  • 3,935
Joseph R.
  • 39,549
  • Hmm, that help is great, I wonder how I've never heard of it... ps2pdf is not that useful since it can't (apparently) create index of any kind. – hyde Oct 15 '13 at 12:04
  • @hyde Not sure what you mean by creating an index, but have you heard of ptx? – Joseph R. Oct 15 '13 at 12:12
  • Index or Table of Contents, that "ptx" sounds exactly like what I meant. – hyde Oct 16 '13 at 07:06
  • 1
    Another, even simpler alternative is to do 'man bash > bashman.txt'. Then you can just open bashman.txt in (another) window in your text editor and use all of it's commands for finding what you want. You can even edit the file to add tags for the sections you refer to most often. Making bashman.txt read-only helps so you don't modify it by accident in your editor. – Joe Oct 20 '13 at 03:58
  • You can also open man pages in the browser of your choice and use all of its tools. See http://askubuntu.com/questions/339255/make-man-pages-open-in-a-web-browser?newsletter=1&nlcode=17739|f2f3 – Joe Oct 20 '13 at 04:00
  • The help command is indeed really cool, pdf text search is bad, regex is much better - steeper learning curve, but worth every minute spent, eventually. – thecarpy Jan 27 '15 at 09:13
9

Approach 1

man bash then /read \[ then /-s

Approach 2

You may try an open source tool for explaining command-line arguments called explainshell.

It can be used locally. Read documentation on https://github.com/idank/explainshell

Caveats: Usually works, but only with commands found in Ubuntu's manpage repository

In your case, it cannot recognize -s switch in read -s pwd.

Approach 3

I have found another tool that seems promising but it does not work on my system.

explain: Short Documentation for Unix Commands

Ivan Chau
  • 720
  • With approach 1, you can do /-s\b to avoid hits like --some-other-command (while still finding strings such as -s,, which you wouldn't get if you searched for /-s with a space). – David Knipe Nov 09 '17 at 20:31
8

What I usually do in this case is just run man, search for the SHELL BUILTIN COMMANDS heading, then search for the builtin, i.e.

man bash
/^SHELL BUILTIN
/  read 

however, in bash you can do

help read

or, depending on the system, either of

man 1 read
man bash-builtins

In general, I have a script called he ("short help") to do this. You would run it like this:

he bash read
Mikel
  • 57,299
  • 15
  • 134
  • 153
3

There is no generic way to finding information in a man page, any more than there is a generic way of finding information in a book. It depends on what you're looking for.

When you're looking for information about a shell builtin, you can search for the builtin at the beginning of a line save for indentation, and followed by a space: search for ^ *read␣ (e.g. type /^ *read␣ Enter) ( is a space). This works with dash, pdksh, mksh and bash. Zsh's man page is split so you need to read the zshbuiltins man page. Ksh93 has special symbols before the names of some builtins, you need to search for ^ *†*␣ in UTF-8 or ^ *-*␣ in ASCII. There are a couple of false positives but this will get you quickly to the right line. Searching for ^ *read($| [-[]) reduces the amount of false positives.

You can speed up the search by telling your pager where you want to go. For example PAGER='less "+/^ *read \["' man bash opens the bash man page on the description of the read builtin. You can make this a function:

man-builtin () {
  PAGER="less '+/^ *$1(\$|\\[|-)'" man ${SHELL##*/}
}
  • In the mksh manpage, / read (two spaces, command name, one space) usually finds the right spot (this is a trick I use myself, and is quick to type). Thanks for asking about it; I’ll put making (somewhat) separate references for all utilities included with mksh on my TODO. – mirabilos Feb 27 '14 at 14:12
  • 1
    @mirabilos / read tends to have a lot of false positives when your man implementation justifies the text. – Gilles 'SO- stop being evil' Feb 27 '14 at 14:37
  • Agreed. Even more reason to really split off the builtin documentation. – mirabilos Feb 27 '14 at 14:40
1

To jump directly to the SHELL BUILTINS COMMANDS section of the bash man page, I define the following alias in my $HOME/.bash_aliases file.

alias man-builtin="man -P 'less -p ^SHELL\ BUILTIN\ COMMANDS' bash"
trellem
  • 31
0

Putting together the pieces from the other discussion here here's a quick function you can leave in your .bashrc that will get you directly to the built-in (if it exists). Otherwise it opens man as normal:

man() {
    case "$(/bin/bash -c 'type -t '"$1")" in 
        builtin)
            LESS=+?"^       $1 " command -p man bash
            ;;
        *)
            command -p man $@
            ;;
    esac
}
Nik V
  • 21
0

From any Linux distro you should be able to use info bash if you want to have separate paragraphs by type of action where the information are identical to man pages.

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
admstg
  • 684
0

I got around to creating a bash function for the purpose. This snippet can be for example pasted at the end of ~/.bashrc:

manfind() {
  # required args
  test "$1" -a "$2" || return 1                  

  # create temp file and get its name
  local tmp=$(mktemp /tmp/manfindXXXXXX) || return 1
  ( # subshell for trap
    trap "rm $tmp" EXIT

    # grep all matching lines with line numbers and pipe them to dialog
    if man "$1" |                   # get the whole man page
      grep -n "^\s*$2" |            # grep for the search string, with line nums
      sed 's/:/\n/' |               # replace line num separator with newline for dialog
      cut -c-70  |                  # cut long lines to nice length
      xargs -d'\n' -n 999999 \
        dialog --output-fd 3 --menu "Select line to go to" 0 0 0 3>$tmp -- 1 '(start of man page)'
    then
      # selected line number is now in $tmp, get man page and
      # use vim in read only mode to view it at right line
      man "$1" | vim -R +"$(< $tmp)" -
    else
      # cancel selected from dialog
      exit 1
    fi
  )
}

Comments explain a bit about what it does. The default search string in particular searches given word from the beginning of lines, skipping initial space. Examples:

# find every line which starts with 'read' followed by space
manfind bash 'read '
# research bash subshells
manfind bash '.*subshell'

Note: This script has no concept of man page sections... I'll see if I tweak that later, but setting MANSECT environment variable of man helps.

hyde
  • 1,288
  • 1
  • 13
  • 20
  • 2
    You might want to add a trap to clean up the temporary file: trap 'rm -f "$tmp"' – l0b0 Oct 15 '13 at 12:34
  • 1
    This looks very complicated. I haven't fully read what your script does, but wouldn't man "$1" | vim -R - "+/$2" do something similar? – Gilles 'SO- stop being evil' Oct 15 '13 at 19:15
  • @Gilles I that would go to first occurrence of $2, so no. – hyde Oct 16 '13 at 05:43
  • @l0b0 Changed cleanup to use trap. I didn't find a clean way to do it in a function without creating a subshell though. – hyde Oct 16 '13 at 07:03
  • @hyde Adapt the regex to what you're doing, of course. My point was about using +/REGEX – Gilles 'SO- stop being evil' Oct 16 '13 at 09:06
  • You might want to trap the default signals (i.e., not specify EXIT) to handle for example Ctrl-C. – l0b0 Oct 16 '13 at 13:33
  • @l0b0 Are you sure that's useful? EXIT seems to trap any exit, for example: (trap 'echo EXITTRAP' EXIT; echo "Press ^C" ; read foo) – hyde Oct 18 '13 at 05:36
  • @Gilles My fingers are really itching to simplify this, especially the pipe which looks like trying to do things completely butt-backwards (to use a US phrase) :)) Like getting the buzz saw from the basement just to cut a 1"-diameter round timber ;)) – syntaxerror Dec 14 '14 at 22:52
  • @syntaxerror If you want to tidy the script up (without changing functionality or introducing other scripting languages, though I suppose I would be ok with awk), feel free to edit... :) – hyde Dec 15 '14 at 20:51
0

Just to offer another alternative, if you prefer using a web browser which allows you to easily search through the current page, you can use something like man.cgi used at freeBSD.org which also lets you view man pages from different systems to see how they differ. I have seen similar on other sites so expect there are other variations around.

The help link under apropos offers some info to get a copy of the script to put on your own server with links to download the man page collections.

sambler
  • 366