Get the top HN stories in your inbox every day.
bfrankline
MontyCarloHall
>From that perspective, it was entirely reasonable to believe that if a command was so complex that it needed options than it was likely more appropriate for one of the other user interfaces
What would the non-shell interface to commands for text processing pipelining (e.g. sort, cut, grep, etc., all of which absolutely need options to function) have looked like? Some people to this day believe that any text processing more complicated than a simple grep or cut should be done in a stand-alone script written in a domain-specific language (e.g. Perl or awk), rather than piping shell commands to each other.
Personally, I’m glad we got the best of both worlds—having command line tools with a dizzying array of options doesn’t preclude being able to accomplish the same tasks with a more verbose stand-alone script. It is often far faster to write shell pipelines to accomplish fairly involved tasks than to write a stand-alone script. The classic example is the (in)famous McIlroy vs. Knuth: six lines of McIlroy’s shell pipeline accomplished the same thing as dozens of lines of Knuth’s “literate program,” while being equally as understandable [0].
>It’s a shame because McIlroy had a lot of interesting ideas around pipelining audio and graphics that, as far as I know, never materialized.
I would love to hear more about this. The UNIX shell is amazing for pipelining (most) things that are easily represented as text but really falls flat for pipelining everything else.
[0] https://leancrew.com/all-this/2011/12/more-shell-less-egg/
svat
> six lines of McIlroy’s shell pipeline accomplished the same thing as
Common misconception. See https://buttondown.email/hillelwayne/archive/donald-knuth-wa... ("Donald Knuth Was Framed") and discussion at https://news.ycombinator.com/item?id=22406070 (etc).
MontyCarloHall
How is it a misconception? My overall point was that shell oneliners are often much faster to quickly bang out for a one-off use case than writing a full program from the ground up to accomplish the same thing. This is demonstrated to a very exaggerated degree in the Knuth vs. McIlroy example, but it also holds true for non-exaggerated real-world use cases. (I had a coworker who was totally shell illiterate and would write a Python script every time they had to do a simple task like count the number of unique words in a file. This took at least 10 times longer than someone proficient at the shell, which one could argue is itself a highly optimized domain-specific language for text processing.)
If your point is that the shell script isn't really the same thing as Knuth's program: sure, the approaches weren't algorithmically identical (assuming constant time insertions on average, Knuth's custom trie yields an O(N) solution, which is faster than McIlroy's O(N*log N) sort, though this point is moot if you use awk's hashtables to tally words rather than `sort | uniq -c`), but both approaches accomplish the exact same end result, and both fail to handle the exact same edge cases (e.g. accent marks).
jlarocco
> What would the non-shell interface to commands for text processing pipelining (e.g. sort, cut, grep, etc., all of which absolutely need options to function) have looked like? Some people to this day believe that any text processing more complicated than a simple grep or cut should be done in a stand-alone script written in a domain-specific language (e.g. Perl or awk), rather than piping shell commands to each other.
I have no idea what the original intention was, but I could see the interface being Emacs or Vi(m).
A workflow I use a lot in Emacs with eshell is to pipe command output to a buffer, manipulate the buffer using Emacs editting commands (including find/replace, macros, indent-region, etc.), and then run another shell command on it, write it to a file, or copy/paste it somewhere else.
It's not for every situation but it's a lot faster than coming up with a complicated shell "one-liner".
msla
The problem there is that you have to rethink your solution if you decide you want to turn your buffer manipulation into a reusable command. I like Emacs, but the easy transition from pipeline to shell script is a big point in pipelines' favor.
layer8
A general tool for that workflow is vipe: https://github.com/juliangruber/vipe
mek6800d2
I haven't looked at this in years, but IIRC Knuth's program could be built and run on almost any OS that had a Pascal (?) compiler, whereas McIlroy's solution obviously required a Unix-like shell, piping, and the necessary commands/tools.
Tijdreiziger
Interesting, any chance you could expand on these 'other user interfaces'? I'm not really familiar with Unix itself, but I've always considered Linux a shell-first OS (as opposed to Windows (NT), which I consider a GUI-first OS).
bfrankline
The other environment that is still popular today is the “statistical environment” that Rick Becker, Allan Wilks, and John Chambers created. It eventually became “S” and John would essentially recreate it as “R.” It’s a very nice environment for performing statistics and graphics together.
imwillofficial
A shell is just how you interact with the underlying system. The gui is also a shell. Confusing I know!
edgyquant
E.g. the Windows GUI is the “Windows Shell,” not be confused with the Windows Command Line which is one (well, many) application within the shell.
daptaq
I like to see it this way: A shell /wraps/ the kernel. You cannot issue system calls directly, but a program that handles user input generically (and ideally dynamically), can do this for you. A desktop environment, Emacs, and to an increasing degree web browsers are all different "shells".
lousyd
Maybe something like Jupyter? Text documents with sections of code or commands?
nmz
FWIW, you can pipe graphics (sort of) with arcan[1]. So its not like the ideas have been abandoned.
jancsika
> It’s a shame because McIlroy had a lot of interesting ideas around pipelining audio and graphics that, as far as I know, never materialized.
Do you know if those ideas are documented anywhere?
bfrankline
The most popular today outside of the shell environment is the statistical environment “S.” John Chambers would recreate it as “R” and I understand that it’s very popular and does a nice job of performing statistics and graphics together.
tambourine_man
Very interesting. We’d love to read more on other media pipelining and alternatives to the shell.
bfrankline
It was very primitive. It was essentially a mechanism for composing operations on vectors. I don’t know for certain but I would guess that it was inspired by IBM and their work on APL.
harry8
Yeah. I wonder if it looks anything like gstreamer...
AlphaSite
I imagine powershell could do this quite well with it’s typed output.
(Not that you can’t just base raw bytes via unix shells but it’s awfully error prone).
pseudostem
Unix history is always fascinating.
>None of this explains dd.
This one really made me think. I have never thought about dd before. Although I have wondered about other commands. Perhaps the author should also have added some command options not requiring a minus prefix, e.g. tar, ps.
The manpage [0] reads:
In the first (legacy) form, all option flags except for -C and -I must be contained within the first argument to tar and must not be prefixed by a hyphen (`-'). Option arguments, if any, are processed as subsequent arguments to tar and are processed in the order in which their corresponding option flags have been presented on the command line. In the second and preferred form, option flags may be given in any order and are immediately followed by their corresponding option argument values.
dredmorbius
dd is a mainframe command, and its syntax follows the JCL conventions used there.
https://www.ibm.com/docs/en/zos-basic-skills?topic=concepts-...
smcameron
Huh. I'd always kind of guessed that dd used if=input-file of=output-file as a way to sort of prevent the use of shell globbing and to not rely on the order of arguments (as cp does) since dd as it is often used can be a bit dangerous (I often found myself using it with disk device files) and you want to be extra careful in specifying the input and especially the output files.
Edit: wikipedia agrees with your IBM origin story https://en.wikipedia.org/wiki/Dd_(Unix)#History
dredmorbius
The syntax is common to most JCL ("job control language") commands. I'd say "all", though there are probably exceptions.
For some reason, this seems to be vanishingly scarce knowledge in Linux / Unix circles.
There was a time in my life I knew how to spell JCL....
thfuran
For safety, selecting arguments distinguished only by choice of two letters adjacent on the most common keyboard layout seems unwise.
elvis70
The parameter names don't seem to match those of dd.
If you type man dd, the function of the tool will be described as "copy and convert". I can't find the video but there is an interview in which Kernighan, I think, explains that the tool should have been named cc but it was not possible because it was already taken by the c compiler.
dredmorbius
The IBM webpage only covers a few of the JCL DD parameters.
There are more at pp. 486ff in Doug Lowe, MVS JCL (1994) here:
http://library.lol/main/6784CBC9EE9BBA5AD26993F497514661
It's still a rather rough fit, though I'm still pretty sure the connection exists.
Keep in mind that Unix dd dates to the early 1970s, and JCL itself may have evolved.
butlerm
The name of dd(1) may have some tenuous connection to the JCL DD statement, but otherwise any similarity seems virtually non-existent. They don't even remotely do the same thing, none of the options or parameters are the same or have similar meanings, or anything like that.
vincent-manis
My understanding is that the name dd was essentially a joke. A DD statement in JCL defined a logical name (seen by the program) to refer to a file (`dataset'). It had many strange operands, and often its behavior was completely unintuitive. For example, here is a job that deletes the file MYFILE.
//MYJOB JOB
//FOOBAR DD DSNAME=MYFILE,DISP=(,DELETE)
//STEP1 EXEC PGM=IEFBR14
IEFBR14 is a program that does nothing at all!Although the Unix dd command wasn't patterned on the JCL command, I suspect that the multiplicity of possible options led its designers to choose the key=value option syntax that looked vaguely OS/360ish.
By the way, the - flag for options first appeared in MIT's CTSS, which was the direct ancestor (at least at the user level) of Multics.
dredmorbius
I'd ... thought that more of the Unix arguments (block, unblock, conv, etc.) were supported on JCL, though my IBM link doesn't support that.
I'll see if I can find a more canonical / complete reference.
GuB-42
dd is fine, at least fine as a disk destroyer can be. It is not standard for UNIX but it is understandable.
tar is a bit messy but the worst is definitely ps. It has dash and non-dash options, and they don't have the same meaning and interact in a weird way.
Edit: the command is "ps", I somehow managed to mess up the most important word...
JadeNB
> tar is a bit messy but the worst is definitely the worst. It has dash and non-dash options, and they don't have the same meaning and interact in a weird way.
Sorry if it should be obvious, but "the worst is definitely the worst" … what is the worst? (Presumably not tar, unless I'm reading incorrectly.)
StringyBob
ps. By far the worst. Because it supports multiple syntax types I can never remember the ps command options. Even if you google for examples you get different syntax and end up with a mix of the same option letters doing different things in one command. It seems to lead to all sorts of subtly unexpected behaviors
lou1306
The best explanation for leaving dd in its original form is that it's not really wise to alter the behaviour of a tool that has been nicknamed "destroyer of disks", regardless of that hot new CLI convention.
teddyh
> I believe the oldest program that uses subcommand is the version control system SCCS, from 1972
IIUC, other non-Unix operating systems commonly used the subcommand style for normal interactive use; it was the style used by the normal command shell, and all commands in those operating systems therefore followed this style. The operating system (or its shell) was responsible for enabling easy use of this style by adding completion support (commonly using the ESC key, IIRC). This older style can still today be seen in Unix tools like ftp and telnet, which uses this style for its internal command line interface. Another tool using this style, which many might be familiar with, is the multi-platform Kermit.
Unix therefore has been rather late in adopting this style, first in gradually adopting tools which uses the subcommand style (ip, git, etc.), and later with support in shells for programmable completion support where a program can optionally register completion hooks for the user shell to use, making it finally come up to the level of those older operating systems.
aap_
The chronology is wrong. dash-options came before pipes. The first edition already has them while pipes came in the third edition.
eesmith
As supporting evidence, the Unix Manual from 1971, http://www.bitsavers.org/pdf/bellLabs/unix/UNIX_ProgrammersM... contains synopses like:
du [-s] [-a] [name ...]
ld [-usaol] name ]
ls [-ltasd] name ...
pr [-lcm] nameMaursault
Wow, that's the actual manual, first edition man pages.
kzrdude
The GNU conventions are terribly convenient. If we were redesigning it from scratch, I'd like to keep all of them except for removing duplicated functionality. One of --long x and --long=x have to go, and that means we only can keep --long=x. And so on.
mort96
I disagree with getting rid of `--long x`. It's really common to build command argvs programmatically, where you have a string representing some option (such as a file path), and you need to pass that as a long option. With `--long x`, you can do like:
char *argv[] = {"my-program", "--config-file", config_file, NULL};
run_command(argv);
With only `--config-file=x`, you would have to allocate memory for the option: char *config_file_opt = asprintf("--config-file=%s", config_file);
char *argv[] = {"my-program", config_file_opt, NULL};
run_command(argv);
free(config_file_opt);
And it becomes even more hairy if you A) want to avoid heap allocation in most cases or B) want to use standard functions rather than asprintf. You'd have to do something like this: char config_file_opt_buf[1024];
char *config_file_opt;
size_t config_file_opt_len = snprintf(config_file_opt_buf, sizeof(config_file_opt_buf), "--config-file=%s", config_file);
if (config_file_opt_len >= sizeof(config_file_opt_buf)) {
config_file_opt = malloc(config_file_opt_len);
snprintf(config_file_opt, config_file_opt_len, "--config-file=%s", config_file);
} else {
config_file_opt = config_file_opt_buf;
}
char *argv[] = {"my-program", config_file_opt, NULL};
run_command(argv);
if (config_file_opt != config_file_opt_buf) {
free(config_file_opt);
}
And even that ignores any kind of error checking of snprintf or malloc which may fail. I also wouldn't even be comfortable assuming the code I just wrote is correct, without thinking long and hard about it and reading standards/documentation thoroughly. Whereas the first example is so simple it's obviously correct.I think we should keep `--long x`. If anything, `--long=x` is the one which should go. There will always be ambiguity; the meaning of something like `-ab` also depends on whether `-a` takes an argument or not.
Really though, I think there are enough situations where `--long=x` is useful that I think keeping both versions makes sense.
mike_hock
You're about to spawn a new process, you can't honestly be worried about a string allocation.
The fact that this is cumbersome in C is fixed by fixing C, not by forcing a pattern onto the ecosystem that only makes sense to work around C's deficiencies.
mort96
I don't think C makes this especially cumbersome, most languages make it somewhat complicated to do format-printing (or string concatenation) into a stack-allocated buffer if it's big enough or fall back to heap-allocating a buffer if the stack buffer is too small.
The argument that you should just heap-allocate because it usually doesn't matter in contexts where you'd spawn a process anyways is a much better argument though. Still, I find the `{"whatever", "--config-file", config_file}` approach much more elegant.
woodruffw
I'll add another minor reason: `--foo="bar"` (with quotes) relies on the quoting/splitting behavior of the shell, which is easy to forget.
For example, someone might write:
args = [cmd, f'--foo="{foo}"']
and expect the surrounding quotes to be stripped off, but that'll only happen if the spawn goes through a shell first. Some argument parsers may also try to strip quotes off, but I don't believe there's any consistent behavior guaranteed around that.jbverschoor
If all of this matters so much, don’t use an (interactive) shell.
mort96
We're not talking about the shell, we're talking about the options parser. Nothing in my examples invokes any shell.
sph
I am annoyed go's flags package did not respect the GNU convention for options, which I agree is the best.
euroderf
Try github.com/spf13/pflag, it handles double-dash arguments OK, and is drop-in.
conaclos
> that means we only can keep --long=x
Just wondering: why `--long=x` over `--long x`?
grose
`--long x` is potentially ambiguous. `x` could be referring to a file if `--long` doesn't take any options, so parsing it correctly depends on this knowledge. The equals sign removes this ambiguity.
twic
If we were starting from scratch, we could require some marker on flags which take values. Perhaps it would have to be `--long: x`. `--verbose x` would be read as a flag with no argument, followed by a positional argument.
kzrdude
--long=x supports the simultaneous --color and --color=auto usecase, i.e the value is optional. Without = it's ambiguous.
jolmg
It also has the advantage that it works with brace expansion to specify multiple values.
--long={foo,bar}
becomes
--long=foo --long=bar
conaclos
With bash/zsh the auto-completion seems missing for unknown options. While `--key file` supports auto-completion since file is just another parameter.
kzrdude
Thanks for teaching something useful!
undefined
layer8
I’m curious why they introduced the ‘=‘ variant at all. Maybe they thought it would be clearer for human readers?
megous
Sometimes I'm glad for public interface ossification. :)
inopinatus
Still waiting for su —-with-wheel-group
euroderf
I come not to bury wheel, but to praise it.
undefined
Maursault
An industry big wheel, a wheel man with nice wheels, put shoulder to the wheel to put wheels in motion spinning wheels to reinvent the wheel before the wheels came off the wagon and squeaky wheel gets the grease. My name is Jonas. I'm carrying the wheel.
nohackeratall
And then you have ImageMagick where the order of flags and options is a science by itself.
sph
Also ps. Everyone uses their own incantation and never strays from it. I use `ps aux` and used to use `ps -def` on Solaris. Some options require a dash, some don’t, it’s such a confusing CLI I never bothered to learn more.
EDIT: also why is `ps` default output so useless? With no arguments it only prints a couple processes and that's it. I have no idea what it's supposed to show me. Talk about bad UX.
floren
Regarding default ps output: remember how people were using Unix in the old days. Logged in via a text terminal on a multiuser system, 99% the only processes you care about are those associated with the current terminal, and that's what ps shows by default. You might have half a dozen backgrounded programs running in that terminal, but that's about it.
Now, my X sessions always have a dozen xterms running and plain ps isn't very useful, but it might break scripts if they changed it...
veltas
Yeah this is the problem, the 'terminal' used to be the box/machine in-front of you. Now a 'terminal' is pretty much just a window or tab most of the time.
undefined
spijdar
In case you're curious, the differences basically stem from BSD and Solaris/POSIX having different command syntaxes, and GNU/Linux's ps command trying to implement both. `ps -ef` is the Solaris syntax, while `ps aux` is from BSD.
kps
Almost. `ps ax` was original Unix form (BSD did add `u`, and later accepted `-` on the flags). `ps -ef` was AT&T System III and descendants.
kitschyred
> Talk about bad UX.
I think you could say this for CLIs in general. While we can all agree that the CLI is great for tasks that require repetition; it's just a PITA for any one-time task. When you just need to do something once and as soon as possible, the manual-help-type-run loop gets tiresome quickly.
Passing options to a program so it can do what most users would want it to do in the first place is nonsensical, and yet that describes the behaviour of many if not all of *nix's tools. It should be the other way around: do what is expected by default, and provide options for different, more uncommon use-cases. Though I suppose this is also a form of baggage from the past that it's very difficult to get rid off because of backwards compatibility.
codethief
Have you tried `ps faux`? :)
wchar_t
Indeed, I passionately hate programs where the order of the options and files/arguments matter just as much as the options themselves.
zvr
Given that ImageMagick can describe a sequence of operations (much like commands piped together), the order is obviously significant.
The exact same holds for ffmpeg command-line.
loudmax
The `find` command is extremely useful, but user-friendly, it is not.
$ find -type f Data/
find: paths must precede expression: `Data/'
find: possible unquoted pattern after predicate `-type'?
sighchengiz
I think Imagemagick and maybe git are where I require a web search most often, along with hope that someone has had the same need before.
jbverschoor
Well magick is more a single live scripting language with multiple paths. While it works, I think it’s the wrong tool for the job
nocman
So you are saying Imagemagick is the wrong tool for any job then? (I ask this because the OP didn't reference any particular task). I would disagree with that. Like many media-related command line tools, it does a lot and therefore has a fairly involved command line interface, but I have found it very useful over the years for processing multiple images (and sometimes even just individual ones).
professorsnep
ffmpeg too! Been doing a lot with it lately and I barely even feel like I have scratched the service of the ffmpeg argument science.
teddyh
> GNU also added standard options: almost every GNU program supports the options --help, --version
GNU keeps a list of them, so that anyone implementing a similar functionality should use the same option if it already exists:
https://www.gnu.org/prep/standards/standards.html#Option-Tab...
protomikron
Interesting is also find. It took me some time to accept that the directory must come first.
E.g.
find /path/to/dir -type f
works, while find -type f /path/to/dir
does not.mort96
Probably helps to think of find as its own weird pipeline rather than a command with options. The first element of the pipeline is the directory(/directories), then `-type f` filters out all the non-files, then `-name '*.txt'` filters out everything which doesn't end in ".txt", etc. That also helps to remember why `-maxdepth` has to be right after the directory; it affects which files even become part of the pipeline, it doesn't make sense as a pipeline element.
The clearest proof that it's a pipeline is probably how it interacts with `-exec`: `find . -type d -exec echo {} \;` will print only directories, while `find . -exec echo {} \; -type d` will print both files and directories.
Regardless though, I sure wish they would let you specify the directories at the end.
yourad_io
Very insightful, I never realized this. Thank you
chubot
I wrote a post about how to understand find syntax:
find and test: How To Read And Write Them
https://www.oilshell.org/blog/2021/04/find-test.html
tl;dr The args AFTER the root dir args form a boolean expression language -- I call it the "I'm too lazy to write a lexer" pattern
find /tmp -type -f -a -name 'foo*'
test is the same way, e.g. test -f /tmp -a -f /binmichaelcampbell
find /tmp -type f -a -name 'foo*' # no "-" for the -type
this is bitten me more often than I'd care to admit.chubot
Oops, good point! Gah
I honestly wonder where this wonky syntax came from ... i.e. was it a Bell Labs thing or later
mmphosis
I just installed tesseract-ocr and it has a similar convention:
tesseract imagename outputbase [options...] [configfile...]tomxor
Yup, always seems to take a bit more conscious effort to remember that detail for find.
onetom
It's interesting, that no one questioned the use of double dash itself.
It looks especially silly, when long options are used to encode some mini programming language (DSL), like in imagemagick and ffmpeg, or when they are used to represent some associative data, like in case of the AWS CLI.
If -- would be a : AFTER the option name, it would look like Objective C named arguments or set-words in REBOL and Red.
If -- would be a : BEFORE the option name, it would look like keywords in Lisps.
As a side-note, shells got quite evolved, actually, but the momentum of the mediocre bash-line prevailed, sadly.
I urge people to learn about es, the Extensible Shell: https://wryun.github.io/es-shell/
Its ancestor, the Plan 9 rc (which I think stands for Run Command) and it used "; " as a prompt, so u could combine multiple commands easier, by copy-pasting whole lines, instead of fiddling with the exclusion of the varying length prompt.
Both of these shells have a lot better string quoting rules than bash, so they play nicer with filenames containing special characters.
They also follow the unix philosophy closer, by not necessarily providing line editing capabilities, which can be added by running them thru eg. rlwrap or not really needed, when running them from Emacs or Plan 9's acme environment.
I would also highlight, that es is just 163KB, while bash is 1.3MB, yet it provides a magnitudes more powerful, dynamic, garbage collected, functional programming language!
theamk
The double-dash is selected for pure practicality.
Any option character excludes a set of inputs, and we want this set to be as small as possible. It is already hard to look at file named "-f" -- do you want to also make accessing files named ":f" (or even worse, "f:") harder? Thus the desire to keep the first "-".
Now, they could have used "-:" or "-=" for long options.. but I think "--" won because it is so easy to type -- no need to move your fingers.
Using long options to encode DSL, like imagemagick and ffmpeg, can be pretty silly.. But those programs are exceptions, and most of the option usage is of much simpler variety. Like "grep --label=input --color=always".
The comments about es sound weird... You can set ";" as prompt in sh/bash too. I would not call its quoting "nicer" -- yes, using '' for a single quote is nice, but lack of " support sounds like a bad omission. Yes, bash is pretty fat by 1990's standards.. but if you want a real programming language with no line editing capabilities, no need to reach for obscure shells -- grab perl, python, tcl, lua or any of the other scripting languages.
onetom
I understand, that the double-dash was a logical step from a single-dash. My problem is, what we ended up with, is really not great. It's a typical case of the slowly boiled frog...
rc and es is an good example of what improvements can be achieved, if we challenge historical decisions and get rid of the not so great ones.
The "; " prompt was just a historical side-note, because I saw someone asking about it the other day on twitter: https://twitter.com/thingskatedid/status/1316081075043463170...
By the quoting rules, I meant, that if you have a variable (eg v='a b') with a value containing whitespace, when you reference it ($v), then you don't have to worry about quoting it in any way, because the space in its value won't cause any problems.
onetom
btw, Rebol solved the mixing of options and filenames by introducing a syntax for file references; u prefix them with a percent sign, eg.:
%/c/plug-in/video.r
%//sound/goldfinger.mp3
%"/c/program files/qualcomm/eudora mail/out.mbx"
%c:/docs/file.txt
%\some\cool\movie.mpg <= understood backslashes too, so it worked in DOS/Windows too!
%cool%20movie%20clip.mpg
Source: http://www.rebol.com/docs/core23/rebolcore-12.html#section-2...
then you could mix them with `:get-words` and `set-words:`. Rebol also had an interesting take on options - with and without arguments -; it called them refinements and you would just stack them with slashes onto the "command". the refinement arguments were added to the end of the parameter list though, so it was not exactly obvious which argument belonged to which refinement, but in practice it worked quite nice, surprisingly:
str: "test"
insert/dup/part str "this one" 4 5
print str
=> this this this this test
and reversing /dup and /part:
str: "test"
insert/part/dup str "this one" 4 5
print str
=> thisthisthisthisthistest
Source: http://www.rebol.com/docs/core23/rebolcore-9.html#section-2....
somat
I have an opinion on this, it is stupid but the more I think about it the more I am convinced I am right.
getopt is lipstick on a pig.
dashed argument are ugly and hard to read.
The worst offenders, programs that implement a language in the args. if you do this just build a proper parser and leave off the dashes. the worst offenders.
iptables find megacli
megacli, remember that? it was the control application for lsi megaraid cards, it was the program that turned me off getopt style args. when I figured out that the megacli parse let you drop the dashes(and the obnoxious capitalization) it was like a breath of fresh air in a fart filled room.
So a better way to do args? use dd style args. Yes dd, dd had it right all this time, I find "key=value" style args to be superior to "--key value" and don't even get me started on the absurdity of "--key=value"
codeulike
I thought Powershell syntax was needlessly confusing until I started writing bash scripts, now I see that ps wasn't so bad.
But I accept why linux command line is the way it is - its a shark, not a dinosaur
jiehong
And then there is also the case of CLIs that aren’t written in C: they don’t get the benefits of a unified getopts lib.
One oddity not explained is tar allowing multi options crammed together without any dash, that nobody can ever remember (eg. tar xvf archive.tar)
LeoPanthera
> One oddity not explained is tar allowing multi options crammed together without any dash, that nobody can ever remember (eg. tar xvf archive.tar)
This is a BSDism, and it's deprecated even there. bsdtar allows it for compatibility with old scripts.
GNUtar has long-switches for all options, which makes it considerably easier to use and understand, for example:
gtar --create --file etc.tar --verbose /etc
nsajko
> This is a BSDism
No, it was like that when Tar was first introduced, as part of Seventh Edition Unix:
eesmith
See also "tap" from v1, to "manipulate DECtape", described at http://www.bitsavers.org/pdf/bellLabs/unix/UNIX_ProgrammersM... , p94 of the pdf:
> tap [key] [name ...]
> The function portion of the key is specified by one of the following letters ...
For example, "x" to extract.
> The following characters may be used in addition to the letter which selects the function desired
For example, "v" for verbose.
elteto
> that nobody can ever remember
These have gone a long way for me:
tar xzf <in> eXtract Zipped File
tar czf <out> <in> Create Zipped File
Anything more complicated and I have to google.Macha
The `-z` on extract is not needed on basically most modern tar implementations (OpenBSD's is I believe the one outlier). tar -xf foo.tar.gz (or .xz, .bz2, .zst, etc.) will work, auto detect the archive type and extract.
aendruk
No need for the mnemonic device when you can literally type “--extract --gzip --file”, which reads as a sentence and has no trouble adapting to --xz or --zstd.
kergonath
> gtar --create --file etc.tar --verbose /etc
That’s considerably more cumbersome than tar -cvf.
teddyh
Or ps, with its BSD and SysV variants. On Linux, the most widely used version of ps uses BSD semantics when using options without a dash, and SysV semantics for dashed options. Thus, both BSD “ps aux” and SysV “ps -fel” work.
1vuio0pswjnm7
"... that nobody can ever remember."
Perhaps it comes down to what programs one uses routinely. Typing "tar xzf" multiple times per week I am unlikely to ever forget it.
Get the top HN stories in your inbox every day.
I was at Bell during the options “debate.” I think something that this otherwise wonderful article misses is that some believed that commands were never intended to be the only way to use the system as the shell was intended to be just one of the many user interfaces that Research Unix would provide. From that perspective, it was entirely reasonable to believe that if a command was so complex that it needed options than it was likely more appropriate for one of the other user interfaces. I believe this is unfortunately now understood by some as it shouldn’t exist. However, because of the seemingly instantaneous popularity of the shell and pipelining text it became synonymous with Unix. It’s a shame because McIlroy had a lot of interesting ideas around pipelining audio and graphics that, as far as I know, never materialized.