41.2 Shell Arguments

Lisp programs sometimes need to run a shell and give it a command that contains file names that were specified by the user. These programs ought to be able to support any valid file name. But the shell gives special treatment to certain characters, and if these characters occur in the file name, they will confuse the shell. To handle these characters, use the function shell-quote-argument:

Function: shell-quote-argument argument &optional posix

This function returns a string that represents, in shell syntax, an argument whose actual contents are argument. It should work reliably to concatenate the return value into a shell command and then pass it to a shell for execution.

Precisely what this function does depends on your operating system. The function is designed to work with the syntax of your system’s standard shell; if you use an unusual shell, you will need to redefine this function. See Security Considerations.

;; This example shows the behavior on GNU and Unix systems.
(shell-quote-argument "foo > bar")
     ⇒ "foo\\ \\>\\ bar"

;; This example shows the behavior on MS-DOS and MS-Windows.
(shell-quote-argument "foo > bar")
     ⇒ "\"foo > bar\""

Here’s an example of using shell-quote-argument to construct a shell command:

(concat "diff -u "
        (shell-quote-argument oldfile)
        " "
        (shell-quote-argument newfile))

If the optional posix argument is non-nil, argument is quoted according to POSIX shell quoting rules, regardless of the system’s shell. This is useful when your shell could run on a remote host, which requires a POSIX shell in general.

(shell-quote-argument "foo > bar" (file-remote-p default-directory))

The following two functions are useful for combining a list of individual command-line argument strings into a single string, and taking a string apart into a list of individual command-line arguments. These functions are mainly intended for converting user input in the minibuffer, a Lisp string, into a list of string arguments to be passed to make-process, call-process or start-process, or for converting such lists of arguments into a single Lisp string to be presented in the minibuffer or echo area. Note that if a shell is involved (e.g., if using call-process-shell-command), arguments should still be protected by shell-quote-argument; combine-and-quote-strings is not intended to protect special characters from shell evaluation.

Function: split-string-shell-command string

This function splits string into substrings, respecting double and single quotes, as well as backslash quoting.

(split-string-shell-command "ls /tmp/'foo bar'")
     ⇒ ("ls" "/tmp/foo bar")
Function: split-string-and-unquote string &optional separators

This function splits string into substrings at matches for the regular expression separators, like split-string does (see Creating Strings); in addition, it removes quoting from the substrings. It then makes a list of the substrings and returns it.

If separators is omitted or nil, it defaults to "\\s-+", which is a regular expression that matches one or more characters with whitespace syntax (see Table of Syntax Classes).

This function supports two types of quoting: enclosing a whole string in double quotes "…", and quoting individual characters with a backslash escape ‘\’. The latter is also used in Lisp strings, so this function can handle those as well.

Function: combine-and-quote-strings list-of-strings &optional separator

This function concatenates list-of-strings into a single string, quoting each string as necessary. It also sticks the separator string between each pair of strings; if separator is omitted or nil, it defaults to " ". The return value is the resulting string.

The strings in list-of-strings that need quoting are those that include separator as their substring. Quoting a string encloses it in double quotes "…". In the simplest case, if you are consing a command from the individual command-line arguments, every argument that includes embedded blanks will be quoted.

Systems running Emacs impose a limit on the maximum total length of a command and its arguments submitted for execution. If a list of arguments to be processed by an external command might be arbitrarily long, then there is a risk of exceeding this limit, in which case executing the command will fail. In some cases this problem can be avoided by running the command multiple times on subsequent partitions of the list of arguments. When you know that it will not cause problems to run the command more than once, you can use this function to preemptively partition a list of arguments:

Function: multiple-command-partition-arguments command arguments &optional shellp

This function returns a list of subsequent partitions of arguments, a list of strings. command is a string or list of strings specifying the command to be run on arguments (unless shellp is non-nil, see below), and including any arguments that must be passed to every invocation of the command. Then, running a command formed of command plus any one of the returned partitions will not exceed the system’s limits on the maximum total length of a command and its arguments.

If optional argument shellp is non-nil, this function implicitly includes shell-file-name and shell-command-switch at the beginning of command (see Creating an Asynchronous Process). In addition, in that case, this function accounts for the extra length taken up by quoting and space characters in its partitioning calculations.

On systems where the process-environment (see Operating System Environment) counts against command line length limits, this function takes that into account too.

In the following example we impose an artificially small limit on command line length and provide a fixed process-environment for demonstration purposes. The partitioning of the list of arguments into two sublists in the returned value implies that running cmd foo bar baz on this hypothetical system would exceed system limits, and thus fail. The calling code should run cmd twice, on each of the two partitions, so cmd foo bar and then cmd baz.

(let ((system-type 'gnu/linux)
      (command-line-max-length 20)
      (process-environment '("BLAH=blah")))
  (multiple-command-partition-arguments "cmd" '("foo" "bar" "baz")))
     ⇒ (("foo" "bar") ("baz"))

This function takes a conservative approach and does not try to minimize the number of partitions of arguments, because doing that would require a great deal of platform-specific information, and also information about encoding which is not currently made available to Lisp.

Variable: command-line-max-length

This variable holds the maximum length of a command and its arguments on this system, measured in characters, as used by multiple-command-partition-arguments.