macOS Bash Command -D: Understanding Its Usefulness

bashcommand linemacos

I'm finally getting around to getting more familiar with the shell after all these years. I was exploring the man page for bash and looking at the -D option, which, according to the manual:

   -D        A list of all double-quoted strings preceded by $ is  printed
             on  the standard output.  These are the strings that are sub-
             ject to language translation when the current locale is not C
             or  POSIX.   This  implies the -n option; no commands will be
             executed.

However, on my mac it generates no output and dumps me into a new shell that seems to have less functionality than the original shell; the which command stopped working in this new shell.

Just wondering if someone can offer insight into what this option is for on the mac. I'm probably using it wrong, I'm sure.

Best Answer

On my mac, bash -D generates no output

bash -D (and its equivalent long option --dump-strings) reads commands from standard input or a file and extracts strings marked as translatable, that is, double-quoted strings that are preceded by a dollar sign, like $"Hello, world".

If bash -D is run without any input, as you did, it outputs nothing and starts a new shell (a special shell, see below.)

For example, for this simple script /tmp/script:

#!/bin/bash
echo $"Hello, world"

bash -D outputs:

"Hello, world"

As you see, this is equivalent to searching for lines that match $"<text>" and removing the dollar sign.

More interesting is the output of the similar option --dump-po-strings, which is, as the Bash man page puts it, equivalent to -D, but the output is in the GNU gettext po (portable object) file format.:

bash --dump-po-strings /tmp/script
#: /tmp/script:2
msgid "Hello, world"
msgstr ""

This excellent article How to add localization support to your bash scripts provides more information on how to use this option.

bash -D dumps me into a new shell that seems to have less functionality than the original shell

That's right, the new shell doesn't react to any commands. The reason for this is that the -D option implies -n, which directs the shell to read commands but not execute them.

The -n option deserves an explanation: although a seemingly useless option at first glance, it is actually quite useful. bash -n does not only read commands but also validates them and complains if the syntax is not valid, so you can run bash -n <script name> to check a script for syntax errors without executing any command.

This means that after executing bash -D, the shell you get will happily accept your commands, check for syntax validity (and output an error if necessary) and do nothing. That's why which "doesn't work".

See Invoking Bash and The Set Builtin sections of the Bash Reference Manual for some background information on this behavior.