* doc/lispref/processes.texi (Shell Arguments): Document it.
* lisp/shell.el (shell-split-string): New function.
@code{combine-and-quote-strings} is @emph{not} intended to protect
special characters from shell evaluation.
+@defun shell-split-string string
+This function splits @var{string} into substrings, respecting double
+and single quotes, as well as backslash quoting.
+
+@smallexample
+(shell-split-string "ls /tmp/'foo bar'")
+ @result{} ("ls" "/tmp/foo bar")
+@end smallexample
+@end defun
+
@defun split-string-and-unquote string &optional separators
This function splits @var{string} into substrings at matches for the
regular expression @var{separators}, like @code{split-string} does
\f
* Lisp Changes in Emacs 28.1
++++
+*** New function 'shell-split-string'.
+This splits a shell string into separate components, respecting single
+and double quotes, as well as backslash quoting.
+
---
*** ':safe' settings in 'defcustom' are now propagated to the loaddefs files.
(push (mapconcat #'identity (nreverse arg) "") args)))
(cons (nreverse args) (nreverse begins)))))
+(defun shell-split-string (string)
+ "Split STRING (a shell command) into a list of strings.
+General shell syntax, like single and double quoting, as well as
+backslash quoting, is respected."
+ (with-temp-buffer
+ (insert string)
+ (let ((comint-file-name-quote-list shell-file-name-quote-list))
+ (car (shell--parse-pcomplete-arguments)))))
+
(defun shell-command-completion-function ()
"Completion function for shell command names.
This is the value of `pcomplete-command-completion-function' for
(should (equal (shell--parse-pcomplete-arguments)
'(("cd" "ba" "") 1 4 7)))))
+(ert-deftest shell-tests-split-string ()
+ (should (equal (shell-split-string "ls /tmp")
+ '("ls" "/tmp")))
+ (should (equal (shell-split-string "ls '/tmp/foo bar'")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (shell-split-string "ls \"/tmp/foo bar\"")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (shell-split-string "ls /tmp/'foo bar'")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (shell-split-string "ls /tmp/'foo\\ bar'")
+ '("ls" "/tmp/foo\\ bar")))
+ (should (equal (shell-split-string "ls /tmp/foo\\ bar")
+ '("ls" "/tmp/foo bar"))))
+
;;; shell-tests.el ends here