Explain Shell
explainshell.com
explainshell.com
Now, I hate to get side-tracked, but for much larger commands, like this one:
ps x -o "%r %c " | grep "someScript.sh" | awk -F' ' '{print $1}' | xargs -I % /bin/kill -TERM -- -%
that has a lot of parts, it can be hard to connect the different options to the various explanations[0], since there are so many lines and they frequently have similar colors and you have to keep scrolling up and down the page. Being able to do something like click on a command/option and have the page jump to the corresponding explanation would be very helpful.[0] - http://explainshell.com/explain?cmd=ps+x+-o++%22%25r+%25c+%2...
find . -type f | xargs wc -l
http://explainshell.com/explain?cmd=find+.+-type+f+%7C+xargs...Arguments to xargs do appear to be parsed, example below:
http://explainshell.com/explain?cmd=find+%2F+-type+f+-print0...
The thing is, I do mean both of the sentiments I shared. I do think it's a fabulous and original idea. I also felt that in one particular use case, it's presentation was a little confusing. Because I'm not the best writer/speaker, it probably came across more insensitively than I was hoping for though.
I agree about large commands being hard to follow. I tried solving this by adding the ability to navigate between commands. Right now clicking the command takes you to a page that displays that command options, but I can change it to the equivalent of navigating to it with the arrows at the top. There might be something better to do UI wise, though.
Possible additions:
- Something that users of the service could add commands to and the community could up vote for grading on technical difficulty.
- Also a "shell command of the day" type of mailer service would be amazing :)
See:
I second the idea in here that the command should somehow stay visible on screen as you scroll down, but is had an even crazier idea: what if you translated a command into paragraph form at the top as a summary?
I might explain `$ grep -nr` to another person as: "search recursively within all files and subdirectories in the current folder and display the results with line numbers" or I might describe `$ du -sh | sort -nr` as ”display the disk used by files and folders in the current directory using human-readable file sizes and sort the output from largest to smallest"
Your tool provides all of this information already, I wonder what it would take to get it that final step to put it into laymans terms while still showing the breakdown of the actual command (which is truly the only way to learn to use it).
Congrats on making such a great tool, I can't wait to tell my friends tomorrow :)
ps -C someScript.sh -o pid= | xargs -I % /bin/kill -TERM -- -%
avoiding two pipes is also 1 femtosecond faster, and as an added bonus HN doesn't trigger the dreaded code scrollbars too!pkill ^someScript.sh$ --signal TERM
Either way pgrep is a nice command to learn about.
Enough gushing, now some bug reports:
"read -r random_line < <(sort -R file)" yields "syntax: expecting filename or fd (position 22)"
"nc HOST PORT | tee movie.mp4 | mplayer -" I can hover over movie.mp4, but I can't scroll down the see the description without losing the emphasis on that path. I'd suggest letting the user click on the portion, or perhaps a long-hover effect?
What if the command was simply pinned to the top of the screen as you scroll down? This would require some trickiness to make the atoms remain connected to their documentation as the documentation slides under the command, but would allow you to view any documentation on the same screen as the command itself.
EDIT: On the other hand, I just noticed that there are buttons to only show the documentation for specific subcommands, so you can always use those to cycle until the documentation you want to see is visible.
>Gorgeous. Amazing. Absolutely fantastic. Easy the coolest and most useful thing I've seen on hacker news in a while.
>Enough gushing, now some bug reports:
I like the way you wrote your comment! It could stand as an example to everyone. Yours might have had enough gushing, but I think every "negative" comment should start with as high praise as it can muster.
If the whole thing isn't as good, then it should first be "damned with faint praise" and then specific constructive criticisms shown. Obviously the praise doesn't have to be as strong as your comment.
I just want to point out how awesome a comment like yours is - it is incredibly hard to put together and share something. We could all do well to remember that when we point out how to improve it.
ACK on the command substitution not working, with the current lexer that I have in place fixing this isn't easy and might take a while. But it's definitely up there on my todos.
Yeah, long pipelines are somewhat of a problem. You can currently navigate the commands with the buttons at the top, maybe they're not visible enough.
But I like the idea of being able to pin a particular line by pressing it, but I fear it might be a bit subtle and easy to miss.
If a JS wiz would like to hack on this I'll gladly help and accept it.
I actually spent a considerable amount of time going over bash's parser [0], and also zsh's [1]. Bash uses lex/yacc with some custom code. zsh seems to have a custom written lexer/parser.
Unfortunately none of them were written to be used as a library, as evident by global state, and a lot of hooks for prompts while parsing, etc. It might be possible to somehow make it work, but it seems like a lot of work to me. You might have an easier time looking at the parser I wrote, and extending that, or rewriting it in another language (as it's fairly small compared to the ones you find in shells). There's also libbash [2], haven't looked closely though.
[0]: http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y
[1]: https://github.com/zsh-users/zsh/blob/master/Src/parse.c
Right now I'm imagining explainphys ;) where each term in a physics equation is explained e.g. The magnetic force felt by a particle of charge q moving with velocity \vec{v} in a magnetic field \vec{B} is
\vec{F}_B = q \vec{v} × \vec{B}
| | | | |______magnetic field
magnetic force | | |
| | cross
charge | prod.
|
velocity of particle[0]: Online version: http://cdecl.org/.
user@server:~$ explain iptables -A INPUT -i eth0 -s ip-to-block -j DROPA new "explain" command could help me, my team, and save us an enormous amount of time getting up to speed on some of our org's long-term system maintenance scripts.
#shutupandtakemymoney (DevOps is fun, teaching not always)
I'd prefer a model where you download a definition file (if it needs to be "updated" at the start frequently)
The main difficulty I had with writing a command line utility is figuring out the UI in a console. Suggestions are welcome of course.
Also, there are two possibilities for a client: the first queries an API on explainshell.com by sending it a command line. This has the advantage of the client being thin, and using the centralized man page database which is probably more accurate. But this means that you're potentially not explaining the exact command you're running locally, which may be confusing.
The second option is to run the man page parser, matcher, etc. locally against the man page on your machine.
However, perhaps the best thing would be to allow both local and remote queries :-)
https://github.com/idank/explainshell
It should be trivial to whip something up that will generate the right URL for a set of arguments, running either on your local web server or against explainshell.com
POST your query, e.g.: tar zcf - some-dir | ssh some-server "cd /; tar xvzf -"
Returns:
[
["tar(1)": "explanatory text"],
["z": "explanatory text"],
["x": "explanatory text"],
["f file": "explanatory text"],
]
etc.Feel free to open a bug and we can discuss the options there.
I suspect what you really want is an iptables demuddler tool that explains the insane "chains" metaphor and explains how individual packets are going to behave. I'd like that too, but it's not this tool.
#!/usr/bin/env python
import sys
import urllib
import webbrowser
url = "http://explainshell.com/explain?cmd=" + urllib.quote(' '.join(sys.argv[1:]))
webbrowser.open_new(url)
(webrowser.open_new doesn't seem to be always working for me, not sure why, I've never used it before)One suggestion though: If there are no command line parameters, then read a line from stdin, so you don't have to play the game of trying to properly escape all of your punctuation in the command line to get it into sys.argv[1:] without any corruption, and can just copy and paste it into stdin.
Hmm, that raises the question of what should happen if you pipe an entire shell script into it, like "./configure"? That might be considered a denial of service attack on explainshell.com.
I wrote this script a while ago. I just needed to update the request because the API had changed a bit since then. Please note that it depends on the scrape tool in the same repository, which in turn depends on the python packages lxml and cssselect. But once you have that set up, you can explain commands from the shell! :-)
$ explain cat filename | sort # won't work
$ explain 'cat filename | sort' # presumably would work
I wonder if the best approach is to make `explain` behave like a prompt. If there was some way it could inherit bash's command history, even better
$ explain
explain> cat filename | sort
The command is: true && { echo success; } || { echo failed; }
But the top box description is for echo parameters. The next one is for echo. Why can't it go from top to bottom in order of the command? EG: Start with true, then &&, then {, then echo, etc.
The way it is, I spend a lot of mental energy matching things up.
Having a single line when you hover could help, but sounds confusing for new users that are unaware of this feature.
tar description1
x description2
z description3
...I understand that the UI looks very nice, but at least for me, having the explanation boxes be in order would make it a lot easier to use. So here is my suggestion:
You can keep everything looking exactly like it is now, except get rid of the lines altogether, and display all of the explanation boxes in order.
When the user scrolls down far enough, display the query at the top of the page with fixed position so that it is always on screen. Then topmost displayed explanation box will get highlighted, along with the relevant portion of the query; unless the mouse is hovering over a certain box or portion of the query, in which case that command/box pair becomes highlighted instead.
If a user tries to scroll with the mouse wheel or keyboard, but there is no more content to display on the page, then the scrolling causes the highlighted box to change instead.
If a portion of the query is highlighted which is not on the page, then clicking that portion will cause the page the jump so that the corresponding box appears and becomes highlighted.
That would be an intuitive UI without relying on wires to connect the content to the sections of the command and it lends itself to responsive layout as well because the command can easily wrap to multiple lines without losing clarity as you read the explanation (where the wires might start to eat into screen real estate at phone width and become much less clear if the command had to be split to multiple lines to stay visible)
There is no perfect solution -- in the ideal world, everyone would use safe healthy programming languages, and nobody would be addicted to shell scripting.
But in the real world, many people still choose to use shell scripting as a quick and easy short term solution to their problems.
Like the unhealthy temptation to use regexps for parsing html, shell scripting just causes more problems, which snowball out of control until you have the dire situation we're in today, with a whole generation of urban hipsters who learned cargo-cult cut-n-paste shell scripting by typing "more ./configure".
So it's much better to treat shell scripting as a health problem rather than a criminal problem.
My only suggestion is that you should sponsor links to "recovery programs," where people can learn to solve their problems with safe healthy programming languages instead of shell scripts. For the popular rube-goldbergesque shell incantations, you could show how to accomplish the same thing more comprehensibly in Python, Ruby, JavaScript, Lisp, Forth, Mathematica, Quartz Composer, etc. ;)
A little one-liner I worked up a few days ago to quickly show me which architecture my OpenWRT trunk was last built with. I'd really like it to explain in much more detail what each of the terms inside the awk command do. Perhaps make "explain" modular so that people can add more detail to the gazillion things that can happen inside awks, seds, greps, etc?
Fabulous idea. This should have been in unix all along as part of the man system.
We should have a `wtf?` command, used like so:
wtf? yes | sudo apt-get install libpq-dev
Results would be ncurses, top line of screen is command with current subcommand highlighted, and rest of screen is less'ed explanation.What is possible and quite easy is creating links for things that are explained in other tools, such as linking the regex argument of grep to some site that explains regular expressions, or somehow integrate it into the existing UI.
Really neat program, nonetheless!
You'll be amazed how many people try this (or other 'malicious' commands), presumably thinking I'm executing the queries. ;)
I'd love to see the argument explanations narrow down sub-arguments. For instance, "find -type f" ought to just show the top-level description for -type and the description for 'f', not all the other type characters.
This is truly stunning. It's a small thing, and what it does is not stupendous. But the design, aesthetics, ease of use, in a word elegance makes the combined whole a superlative tool.
Also missing some obvious things like on this basic zip command [0]. It can't explain -9, probably because that's not in the man page as itself but as "-n". But also has nothing to offer about the zip file target or the input folder, which are in the man page as symbolic arguments.
[0] http://explainshell.com/explain?cmd=zip+-vr9+foo.zip+somefol...
Alternatively, I was thinking there might be a nice "swipe" or "carousel" interface applicable here. e.g. you hit left/right arrows and it explains every individual atom of the command-line.
That said, very nice as it is now. You deserve major kudos simply for bringing most manpages online in a searchable, good-looking interface! Instantly added as a "dev" bookmark for me.
sudo apt-get install tree Only sudo is explained. I understand apt-get is distro-specific, but it's widespread enough to deserve a special case. Interestingly, apt-get install tree (without sudo) works better.
Common, widely known system configuration files like /etc/issue, /etc/hosts, /etc/hostname, /etc/fstab ... deserve to be special-cased, too. Many of them actually have their man pages, so it's possible to script.
I only scanned sections 1 and 8 of the man page archive, so that's why files are missing.. but they can be added.
If you were to open up donations to support development, I would HAPPILY contribute.
I work full-time right now, so money isn't really an issue. I'll gladly accept commits though! ;)
It had difficulty with:
find . -name ".cpp" | xargs -i grep -His "oops" "{}"
http://explainshell.com/explain?cmd=find+.+-name+%22*.cpp%22...
It seems to think the -His belongs to xargs rather than grep.
for FILE in `ls`; do echo $FILE ; done
http://explainshell.com/explain?cmd=+for+FILE+in+%60ls%60%3B...That's a simpler equivalent of something I cooked up which probably didn't belong in a single line of shell anyhow.
The bigger problem is grep. We're told that grep prints lines matching a pattern, great. But then the explanation of the arguments makes it sound, to the uninitiated, like I'm giving "foo" as the filename, because the site doesn't include the actual grep syntax.
It doesn't really explain what the command line is doing. It does seem to do a decent job of telling someone who's already fluent in shell usage the specific meaning of all options given. That's actually pretty important these days where any given GNU util will have flags for every single letter of the alphabet in both upper and lower case.
% find . -path '*foo*'
You need -path, not just -name, to match the whole name as du does.But, your detractors will say yours is two processes and theirs is one. Efficiency!
A word is standardized as 5 keystrokes
80 wpm is therefore 400 keystrokes per minute.
Divide by 60 to get about 6.6 keystrokes per second, or about 0.15 seconds per keystroke.
Therefore it would take about 0.6 seconds to type the four extra characters, giving a net savings to use du+grep instead.
And 80 wpm is probably a rather fast estimate; I'd guess that I type slower when I'm writing commands than when I'm entering English text.
(while :; do cat ; sleep 2 ; done) <fileAlso, what an odd one-liner. What's the use case for this that makes it such a common command: file names and sizes for all files matching a pattern beneath the current subdirectory (and all subdirectories and files within subdirectories matching that same pattern)? Genuinely curious.
GREAT: find / -type f -print0 |xargs -0 grep heythere
I tried some sub-shells, and seemed to not work so well. $() and `` would be nice.
ps -fp $(pgrep -d, krb5kdc)
ps -fp `pgrep -d, krb5kdc`
http://explainshell.com/explain?cmd=ps+-fp+%24%28pgrep+-d%2C...
edit: newlines
tar cf - . | (cd /dest/dir ; tar xvf -)
Which uses tar to copy a directory tree. It didn't know '.' stood for the current directory, it missed out that 'f -' was the file "standard in" / "standard out"Of course those things might not be true any more, basically I got habituated to using it when I was Sun and it continues to work, so my fingers haven't tried to learn a new pattern.
A nice to have: Having the command that was originally entered follow you down at the top of the window so when I'm looking at a long piped command, it makes it easier to follow
echo `uptime|grep days|sed 's/.up \([0-9]\) day.*/\1\/10+/'; cat \ /proc/cpuinfo|grep '^cpu MHz'|awk '{print $4"/30 +";}';free|grep \ '^Mem'|awk '{print $3"/1024/3+"}'; df -P -k -x nfs | grep -v \ 1k | awk '{if ($1 ~ "/dev/(scsi|sd|md)"){ s+= $2} s+= $2;} END \ {print s/1024/50"/15+70";}'`|bc|sed 's/\(.$\)/.\1cm/
One small change request: the longer commands make me scroll down the page, and I can no longer see what each block is pointing to. Maybe you could fix the command to a top-bar as you scroll down?
for x in `ls ~/foo`; do echo $x; done
doesn't yield anything remotely interesting. for x in $(ls ~/foo); do echo $x; done for word in foo bar baz; do echo $word; done
Seems to think COLUMNS is a command in: COLUMNS=20 lsI did choke at the end of this little favorite:
find -name "*.[hc]" -o -name "*.[hc]pp"|xargs grep -siP 'apa'To improve: it didn't provide any context to what $IFS is used for.
Why are you using bootstrap if the site isn't responsive?
The !! command is used to repeat the previously issued command.
cat fil*.dat | head -100 | tail -20. Does not explain -100 in head and -20 in tail.
: abc $(xclock) def