getopt‐style options to dd
The dd command first appeared in the Unix 6th Edition's manual, putting its creation some time between 1972 and 1974.
This long pre‐dated the invention of the getopt() library function, which was apparently invented by AT&T for Unix System 3 in 1980.
Both were standardized in POSIX.1 in 1988, and are in the Single Unix Specification version 8 as dd and getopt, which also codifies the latter's behaviour as the 'utility syntax guidelines'.
Eric Foxley's UNIX for Superusers, published in 1985, shows that this was some years in the making, as it documents the 'Proposed syntax for Unix commands' in almost its same form as the SUS of 2024 still has it, in appendix 5.
There was actually a push to 'getopt()ify' utilities consistently through the 1980s and early 1990s, including — not least — Marc Teitelbaum switching ps in 4BSD to using the getopt() library function on 1990-04-02 (an important milestone in the history of the ps command).
Famously, dd was one of the hold-outs against this.
It started with a syntax that had echoes of the 'Data Definition' syntax of JCL on 1960s mainframe operating systems.
Having a JCL-like option syntax is how it has been long described, although it was never referred to as that in the Unix manuals (which called it things like 'copy and convert files') and it does not really have the syntax of JCL data definitions, which has all sorts of things like parentheses and structured values and making comma‐separated rather than whitespace‐separated lists of key=value pairs.
Peter da Silva described dd in 1989 as one of the 'Big Two' exceptions to the Unix command syntax standard, the other being find.
As of 2026, dd's option syntax had not changed in at least 52 years, and no‐one had (from my research) even seriously mooted the idea.
That is, until Aris Adamantiadis came along.
On 2026-08-30, as part of a semi‐serious FediVerse thread about the ways that one can make mistakes with dd Aris Adamantiadis wrote:
I'd totally adopt a dd that has a syntax like dd --source /dev/urandom --destination some_random_file --count 1024 --unit KiB
I opined that that sort of thing would happen just before Sol turned into a red giant star.
But I am the person who re‐wrote the ul manual to include its undocumented behaviour that had existed since the time of Bill Joy at Berkeley; who proved the nay‐sayers wrong who 'explained' that ifconfig could not be changed to use Linux features so a completely new ip command had to be written, by making a cross‐platform ifconfig that used the Linux mechanisms that supposedly one could not write code to use; and who followed up on my own 2006 proposal by writing a user‐space virtual terminal system (for more than just Linux, c.f. the Guide).
So I went ahead and actually wrote the code.
After all, that is not the hard part.
The plan9 people changed their dd to use single minus signs for long options, but they did not use getopt() (their code rolls its own nonce argument parsing) and they did not create a syntax that actually conforms to the 1980s Unix syntax rules (because it looks like loads of single‐letter options by those rules).
I instead used the getopt_long() C library function that is in the GNU C library, the musl C library, and, since the turn of the 21st century, the BSDs (NetBSD, OpenBSD, FreeBSD, DragonFlyBSD) and Illumos C libraries.
It was added to NetBSD in 2000, the work of Thomas Klausner and Dieter Baron, and had been included in the FreeBSD and OpenBSD C libraries for about 24 years.
The OpenBSD import was done by Todd C. Miller in 2002.
Miller's version is what Illumos has, added at some point before Solaris was open sourced as OpenSolaris in 2005.
This of course yields the SUS standard option behaviour, assuming that the library is not erroneous (If it is, that is a C library problem.), without nonce home‐grown option parsing.
The code adds a second long option syntax.
(dd has, after all, had long options since 1974.
"conv" is not a short single‐letter option.
Why, it is almost a whole real English word! ☺)
This is a "getopt‐style" syntax where the 1974 one was "JCL‐like".
The getopt‐style long option syntax does not change the names of the long‐standing long options.
The former's names are just the latter's with two minus signs.
The equivalent to the JCL‐like iseek in getopt‐style is --iseek.
However, some convenience real‐English‐word aliases have been added.
The equivalent to the JCL‐like iseek in getopt‐style is additionally --input-skip.
In action, it looks like this:
% dd --if /dev/zero --of /dev/null --count 7 --bs 8192 7+0 records in 7+0 records out 57344 bytes transferred in 0.000025 secs (2290649225 bytes/sec) % dd --input-file /dev/zero --output-file /dev/null --count 7 --block-size 8192 7+0 records in 7+0 records out 57344 bytes transferred in 0.000024 secs (2381368006 bytes/sec) %
I was not going to add a short option syntax, initially, as dd has never had short options, and also because picking from a limited 52‐letter set yields some hard choices when so many of the long options begin with 'i', 'o', and 'c'.
Then Leah Neukirchen pointed out the rw command in Sortix (which does not do the conversion part of 'copy and convert files').
The Sortix people had already invented a short option set for a quite similar, but not identical, tool.
So I nicked it.
The code adds a third short option syntax. In action, it looks like this:
% dd -i /dev/zero -o /dev/null -r 66 -w 132 -n 7 -I 9 7+0 records in 3+1 records out 462 bytes transferred in 0.000019 secs (24528715 bytes/sec) %
One important thing to note is that by design one cannot mix getopt‐style and JCL‐like long options in a single command invocation.
That would be a recipe for confusion in the future.
One can mix long and short getopt‐style options, as one can in other commands, since this is a function of getopt_long().
I have modified several dd commands, plus some other things.
The patch to FreeBSD 10.3 dd and its manual is in my fork of PC-BSD/TrueOS 10.
I did patch a later version as well, but was unable to test it.
The patch to dd.c in GNU Core Utilities 9.11 is included in my slashpackage packaging of GNU coreutils.
In an ideal world, someone would put this into GNU coreutils. However, I have no idea who is nowadays responsible for this part of GNU Core Utilities, and likely no way to contact them even if I knew their names.
In this world, a Debian user who is au fait with the command line could just apt-get source coreutils, plonk the patch into debian/patches, and then dpkg-buildpackage some binary packages to install locally from file.
The diff in the patch is one subdirectory down from where Debian expects things to be, and might require a dummy top‐level directory being prepended; but that is about it.
Likewise, the patch should just drop in to the sysutils/coreutils port in the FreeBSD ports tree.
The diff is at the same subdirectory level that FreeBSD ports patches are at.
Although if one were using FreeBSD, it's more sensible to patch the native FreeBSD dd in /usr/src/bin/dd with one of the FreeBSD patches.
Note that GNU Core Utilities generates manual pages from --help output, so this will also result in a revised dd.1 manual.
The patch Completion/Unix/Command/_dd for the Z shell's completion system is included in my slashpackage packaging of the Z shell.
The Z shell's completion system has a feature where if a command supports --help it will execute the command with that option, and present the results in its completion menu, completing both long and short options, as long as the help output is getopt‐style.
This work adds a working --help to dd that prints getopt‐style option help; and thus this Z shell mechanism now works at long last without having to hardwire a list of options into the Z shell's completion system.
(This applies to the second and third option syntaxes; the first one, the old 1974 one, still has to have special knowledge in the Z shell.)
The prediction about Sol going red giant still stands. I also made several other predictions about people's reactions.
But everyone will have to change their doco and scripts!
Amusingly, the only people to whom this actually should be said are the Plan9 people, whose dd command is not backwards compatible.
This work keeps the old JCL-like option syntax exactly as‐is, to the point of the code changes even being arranged so that it is blatantly apparent from the diffs that the old option‐handling code is untouched, as is all of the code that performs the actual copying and conversion work after the option parsing has been done.
No scripts need be changed, unless one likes SUS standard option processing; and the options and examples in the old books continue to work.
So go tell it to Pike, Ritchie, Thompson, Kernighan, Stroustrup, et al.. ☺
It should be called something other than dd.
No, it should not; no more than Teitelbaum's change to ps meant that we should have stopped calling it ps in 1990, or than Hugh Smith's. change to ar to employ getopt() meant that we should have stopped calling it ar in 1991, or than Marshall Kirk McKusic's change to dump to employ getopt() meant that we should have stopped calling it dump in 1995.
getopt()ification does not change what the tool is, and there is ample evidence of this.
What this really is is the sort of combination of helpless and pessimistic and reinvention churn thinking that got us ip instead of improvements to ifconfig, in the Linux world.
The optimistic counter is that, as can be seen, the world did this, to not just BSD programs but also shareware and Usenet-posted stuff of the time; and none of what people claim, or said has to happen, actually happened or needed to happen.
BSDs do not use long options. It is counter to BSD culture.
This may have been somewhat true as the knee‐jerk 'not invented here' reaction in 1989 when long options arrived in GNU code (although, as noted, they had been in Unix, in this very dd command, since 1974, and in other operating systems before AT&T even invented getopt(), vide DCL in RSX-11 and CCP in CP/M 3).
But it is 2026 now, and the people who were not even born when GNU played catch up with both Unix and other systems are now approaching middle‐age, and looking at the range of existing programs in NetBSD (e.g. chmod since 2011, diff3 since 2025, and sdiff since 2007) and OpenBSD (e.g. compress since 2002, seq since 2022, diff since 2003, and file since 2015) that nowadays have long options and wondering whether the people who claim that the BSD world objects to long options have actually looked at the BSD world at all in the 21st century.