Script to Make an Annotated list of all Shell Commands.

Once again, someone showed me how much easier my life would be if I merely used a Unix command that I didn’t know existed: http://macscripter.net/viewtopic.php?pid=171501#p171501

There has got to be a better way of getting aquainted with these things than reading all the man pages, or spending a decade learning by osmosis.
I wrote a little script that looks like it’ll be quite helpful in this regard:

-- Make Annotated Shell Command List
-- BP 2014
-- Just run this script, wait a few minutes, and copy the result into your favorite text editor
-- You'll have a searchable list of all (most) of the terminal available commands on your Mac
-- With a short, searchable, description of what each command does.
--
--    Note This'll take a few minutes to run, there's about 1500 commands to look at
----------------------------------------------------------------------------
set annotatedcmdlst to {}

set cmdslist to paragraphs of (do shell script "compgen -ca")

--set oldtid to AppleScript's text item delimiters
--set AppleScript's text item delimiters to "\r"
--set thetext to every item of cmdslist as text
--set AppleScript's text item delimiters to oldtid
--return thetext  ------------------------------------1497 lines of commands

set end of annotatedcmdlst to "builtin - shell built-in commands   --There are lots of these, in very long and unenlightening lines. Use 'man builtin ' to see  them"
repeat with n in cmdslist
	set thecmd to (quoted form of n) as text
	--set end of annotatedcmdlst to do shell script "whatis " & thecmd ----------- 14517 lines.  This needs a clean up.
	set tem to (do shell script "whatis " & thecmd) as text
	if tem does not contain "::" then -- Don't care double colon rules here anyway.  So eliminate their lines
		if "builtin" is not in tem then -- kill the multiple copies of "builtin - shell built-in commands" -- 2124 lines mostly readable wo this
			set end of annotatedcmdlst to tem ------------------- This gets me down to 1972 lines, which is mostly readable
		end if
	end if
end repeat

set oldtid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "\r"
set thetext to every item of annotatedcmdlst as text
set AppleScript's text item delimiters to oldtid
return thetext -- Saved as a text document, this is nicely searchable

Having saved the script’s output to BBEdit, the tr command noted in the link above shows up as the 5th hit on a search for “charact.” The line looks like this:
tr(1) - translate characters
Easy-Peasy.

I know the shell’s built in commands are still hidden behind ‘man builtin’, and haven’t checked yet if developer tools made it into the script output, but this is a big step up from trying ‘apropos…’ on half a dozen different strings and hoping for a good hit

Great indeed! Thanks for sharing!
I had to add “quoted form of” though in order to get it run without error:

	set thecmd to (quoted form of n) as text

Then many commands are said to have nothing appropriate. Should probably delete those to get sth slim.

So here is the code I end up with:

-- Make Annotated Shell Command List
-- BP 2014
-- Just run this script, wait a few minutes, and copy the result into your favorite text editor
-- You'll have a searchable list of all (most) of the terminal available commands on your Mac
-- With a short, searchable, description of what each command does.
--
--    Note This'll take a few minutes to run, there's about 1500 commands to look at
----------------------------------------------------------------------------
set annotatedcmdlst to {}

set cmdslist to paragraphs of (do shell script "compgen -ca")

--set oldtid to AppleScript's text item delimiters
--set AppleScript's text item delimiters to "\r"
--set thetext to every item of cmdslist as text
--set AppleScript's text item delimiters to oldtid
--return thetext  ------------------------------------1497 lines of commands

set end of annotatedcmdlst to "builtin - shell built-in commands   --There are lots of these, in very long and unenlightening lines. Use 'man builtin ' to see  them"
repeat with n in cmdslist
	set thecmd to (quoted form of n) as text
	--set end of annotatedcmdlst to do shell script "whatis " & thecmd ----------- 14517 lines.  This needs a clean up.
	set tem to (do shell script "whatis " & thecmd) as text
	if tem does not contain "nothing appropriate" then
		if tem does not contain "::" then -- Don't care double colon rules here anyway.  So eliminate their lines
			if "builtin" is not in tem then -- kill the multiple copies of "builtin - shell built-in commands" -- 2124 lines mostly readable wo this
				set end of annotatedcmdlst to tem ------------------- This gets me down to 1972 lines, which is mostly readable
			end if
		end if
	end if
end repeat

set oldtid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "
"
set thetext to every item of annotatedcmdlst as text
set AppleScript's text item delimiters to oldtid
return thetext -- Saved as a text document, this is nicely searchable

I think this does the same but only slimmed down to one line:

do shell script "whatis $(compgen -ca) | egrep -v '(::|builtin|nothing appropriate)'"

I get 9610 lines of output when I run that, and only 1972 lines when I run my script. Looks like a lot of, for example “\rTcl” items are making it through your filter that are stopped by mine.

Likely depends on what commands you have installed, and I got lucky. I’ve changed the original source to reflect that.

I didn’t know that was important: Your command prints kernel commands (syscalls) as C library functions etc… :slight_smile:

Here an improved filter that will only print the appropriate commands (user, miscellaneous and system commands):

do shell script "whatis $(compgen -ca) | egrep '^[^ ]*\\([178]\\)' | egrep -v '(builtin)' | sort -u"

Now that looks pretty sweet.
At 1574 lines returned, it’s only a few more than “compgen -ca”, and you’ve alphabetized the listing. :smiley:

I print only commands that ends with (1), (7) or (8).

1 General commands (tools and utilities) (man 1 intro)
2 System calls and error numbers (man 2 intro)
3 C libraries (man 3 intro)
4 Devices and special files (no introduction for this section)
5 File formats (man 5 intro)
6 Games (no introduction for this section)
7 Miscellaneous information pages (man 7 intro)
8 System maintenance and operation commands (man 8 intro)

You could leave the 7 out of grep but sometimes an more throughly explanation can be found about certain commands which will be showed now, could be useful in some rare cases.

I’ve alphabetized the list so I could also get rid of double entries in the list :slight_smile:

Hello.

Here is my take, as DJ’s above, but I have removed perl and python references, and I also had to clean the listing a little, which may be just my installation.

do shell script "whatis $(compgen -ca) | egrep '^[^ ]*\\([178]\\)' | egrep -v '(builtin|nothing appropriate|perl|python)' | sort -fu |sed -e 's/rst2man.*$//g' -e 's/\\([^\\.][^\\.]*[\\.][ ]\\)\\(.*\\)/\\1/g'"

Hello.

This was really a progress. (At least as long as I haven’t installed Tc/Tkl!

Here is a script to run it from the script menu, but it can be saved as an app too. The idea is that you supplement it with your personal commandset.

The idea behind the apropos command: you write ‘apropos db’, and you get every line with db in it.

This works like this, but it also remember the last search, so that if you just hit enter, then you’ll see the last , which will be displayed in a dialog, if it was just a line, or in a new Text Edit document if there were many hits.

property script_title : "Bash command names"
script bash
	(*
		This is the list from the do shell script command.
		I did two search and replace operations in text edit.
		1.) I escaped all double ticks.
		2.) I embedded the lines in a lists which I then pasted into the {} of the aprops_lines {} (empty list).
		the data below is just an excerpt to illustrate what it looks like.
	*)
	property apropos_lines : {{"7z(1)                    - A file archiver with highest compression ratio"}, ¬
		{"7za(1)                   - A file archiver with highest compression ratio"}, ¬
		{"7zr(1)                   - A file archiver with highest compression ratio"}, ¬
		{"822-date(1)              - Print date and time in RFC2822 format"}, ¬
		{"a2p(1)                   - Awk to Perl translator"}, ¬
		{"a2ps(1)                  - format files for printing on a PostScript printer"}, ¬
		{"aafire(1), aainfo(1), aasavefont(1), aatest(1) - aalib example programs"}, ¬
		{"ab(8)                    - Apache HTTP server benchmarking tool"}, ¬
		{"ac(8)                    - display connect-time accounting"}, ¬
		{"...2300 more items..."}, ¬
		{"zshoptions(1)            - zsh options"}, ¬
		{"zshparam(1)              - zsh parameters"}, ¬
		{"zshroadmap(1)            - informal introduction to the zsh manual The Zsh Manual, like the shell itself, is large and often complicated. "}, ¬
		{"zshtcpsys(1)             - zsh tcp system"}, ¬
		{"zshzftpsys(1)            - zftp function front-end"}, ¬
		{"zshzle(1)                - zsh command line editor"}}
end script

property answer_list : {}
property previous_answer : "Enter term here:"

on main()
	local searchterm
	tell application id "com.apple.systemuiserver"
		set searchterm to text returned of (display dialog "Apropos term: " default answer my previous_answer with title script_title with icon 1)
	end tell
	try
		if ((offset of space in searchterm) ≠ 0) or ((offset of tab in searchterm) ≠ 0) then
			# we clean up the searchterm for leading whitespace
			repeat while text 1 of searchterm is space or text 1 of searchterm is tab
				set searchterm to text 2 thru -1 of searchterm
			end repeat
			# we clean up the searchterm for trailing whitespace
			repeat while text -1 of searchterm is space or text -1 of searchterm is tab
				set searchterm to text 1 thru -2 of searchterm
			end repeat

		end if
	on error e number n
		set searchterm to "-NONE-"
	end try
	
	if searchterm = my previous_answer then
		showResult(searchterm)
	else if searchterm is not "-NONE-" then
		set found to false
		set answer_list to {}
		repeat with i from 1 to (count bash's apropos_lines)
			set this_line to (item i of bash's apropos_lines as text)
			if searchterm is in this_line then
				set end of answer_list to this_line
				set my previous_answer to searchterm
				set found to true
			end if
			
		end repeat
		
		if found then
			showResult(searchterm)
		else
			
			tell application id "com.apple.systemuiserver"
				display dialog "No match for searchterm: " & searchterm with title script_title buttons {"Ok"} default button 1 with icon 2
			end tell
		end if
	else
		tell application id "com.apple.systemuiserver"
			display dialog "Missing searchterm: " with title script_title buttons {"Ok"} default button 1 with icon 2
		end tell
	end if
end main

on showResult(searchterm)
	if (count answer_list) = 1 then
		
		set my previous_answer to item 1 of answer_list
		
		# we remove superfluos white space to display the result in the dialog more orderly.
		repeat while my previous_answer contains space & space or my previous_answer contains tab
			tell (a reference to my text item delimiters)
				set {tids, contents of it} to {contents of it, space & space}
				set probe to text items of my previous_answer
				set contents of it to space
				set my previous_answer to probe as text
				set contents of it to tab
				set probe to text items of my previous_answer
				set contents of it to space
				set my previous_answer to probe as text
				set contents of it to tids
			end tell
		end repeat
		
		
		tell application id "com.apple.systemuiserver" to display dialog my previous_answer with title script_title buttons {"Ok"} default button 1 with icon 1
		
	else
		if searchterm does not contain "Result for 
" then set my previous_answer to "Result for 
" & searchterm
		if not running of application id "ttxt" then tell application id "ttxt" to launch
		tell application id "ttxt"
			tell text of (make new document)
				repeat with aLine in my answer_list
					make new paragraph at end of it ¬
						with data ¬
						((aLine as text) & linefeed) with properties {font:"Menlo", size:12}
				end repeat
			end tell
		end tell
		do shell script "open -b com.apple.textedit"
	end if
end showResult

main()

Hello.

I polished it a little:

When there are just one answer to the query, so that I can display it in a dialog, then I remove all superfluos whitespace, in order to have an orderly looking dialog box.

I think I have made the dialog, that represents the searchstring for a query that returned multiple matches better too.

Edit

I also print any “report” with the monospaced font meno, so the dashes even up line by line.