Shell Command Support
The :std/cli/shell
library provides facilities for working with Unix shell code
usage
(import :std/cli/shell)
An earlier version of this library used to be available as :clan/shell
in gerbil-utils.
Interface
easy-shell-character?
(easy-shell-character? character) => bool
Returns true if the character
if a string may contain the character in any position
without that this fact requiring the string to be quoted in any shell.
This include alphanumeric characters and those in "@%-_=+:,./"
(not including the double quotes).
All other ASCII characters may require the string to be quoted. For good measure we also quote strings containing non-ASCII characters.
Examples:
> (string-for-each (lambda (c) (or (easy-shell-character? c) (error "foo")))
"abcdefghijklmnopqrstuvwxzABCDEFGHIJKLMNOPQRSTUVWXZ012345678@%-_=+:,./") ;; no error
> (string-for-each (lambda (c) (or (not (easy-shell-character? c)) (error "foo")))
"!`~#$^&*()[{]}\\|;'\"<>? \r\n\t\v") ;; no error either
needs-shell-escape?
(needs-shell-escape? string) => bool
Returns true if the string
is known not to require quoting in a Unix shell.
The current implementation only trusts strings where every character
satisfies easy-shell-character?
to not require quoting.
Examples:
> (map needs-shell-escape ["foo?" "~user" "$1" "*.*" "!1" "ab\\cd" "{}" "a;b" "&" "|" "a b c"])
(#t #t #t #t #t #t #t #t #t #t #t)
> (map needs-shell-escape ["foo" "%-_=+:,./" "1" "..." "abcd" "x=y:z,t.z/u+v_w"])
(#f #f #f #f #f #f)
escape-shell-token
(escape-shell-token string) => shell-escaped-string
Given a string
, returns a shell-escaped-string that,
when included in a Unix shell command, will expand into the input string
.
Examples:
> (map escape-shell-token ["foo?" "~user" "$1" "*.*" "!1" "ab\\cd" "{}" "a;b" "&" "|" "a b c"])
("\"foo?\"" "\"~user\"" "\"\\$1\"" "\"*.*\"" "\"!1\"" "\"ab\\\\cd\"" "\"{}\"" "\"a;b\"" "\"&\"" "\"|\"" "\"a b c\"")
> (let (l ["foo" "%-_=+:,./" "1" "..." "abcd" "x=y:z,t.z/u+v_w"])
(equal? l (map escape-shell-token l)))
#t
->envvar
(->envvar . str) => environment-variable-name
Given a list of arguments str
, return a string to be used as
a shell environment variable name following the convention of having
only upper-case ASCII letters and digits and underscores.
The arguments are passed to as-string
then uppercased, and
any non-empty sequence of characters other than letters and digits
are replaced by a single underscore.
Examples:
> (->envvar "foo")
"FOO"
> (->envvar "bar baz")
"BAR_BAZ"
> (->envvar '("bar " "+!@#$") #(#\@ #\! "#") "baz")
"BAR_BAZ"