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 in some circumstances. For good measure we also quote strings containing non-ASCII characters.
Examples:
> (string-for-each (lambda (c) (or (easy-shell-character? c) (error "foo")))
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@%+,-./:=@_") ;; 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
contains any character known or suspected
to sometimes or always require quoting in any Unix shell.
The current implementation only trusts strings where every character
satisfies easy-shell-character?
to not require quoting.
Examples:
> (andmap needs-shell-escape? ["foo?" "~user" "$1" "*.*" "!1" "ab\\cd" "{}" "a;b" "&" "|" "a b c"])
#t
> (ormap needs-shell-escape? ["foo" "%-_=+:,./" "1" "..." "abcd" "x=y:z,t.z/u+v_w"])
#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"