blob: e428b51912c29c234fd8f12fe5e22e159eafee4f [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package shutil provides shell-related utility functions.
package shutil
import (
"fmt"
"regexp"
"strings"
)
const (
// The character class \w is equivalent to [0-9A-Za-z_]. Leading equals sign is unsafe in zsh,
// see http://zsh.sourceforge.net/Doc/Release/Expansion.html#g_t_0060_003d_0027-expansion.
leadingSafeChars = `-\w@%+:,./`
trailingSafeChars = leadingSafeChars + "="
)
// safeRE matches an argument that can be literally included in a shell
// command line without requiring escaping.
var safeRE = regexp.MustCompile(fmt.Sprintf("^[%s][%s]*$", leadingSafeChars, trailingSafeChars))
// Escape escapes a string so it can be safely included as an argument in a shell command line.
// The string is not modified if it can already be safely included.
func Escape(s string) string {
if safeRE.MatchString(s) {
return s
}
return "'" + strings.Replace(s, "'", `'"'"'`, -1) + "'"
}
// EscapeSlice escapes a slice of strings so each will be treated as a separate
// argument in the returned shell command line. See Escape for more information.
func EscapeSlice(args []string) string {
escaped := make([]string, len(args))
for i, arg := range args {
escaped[i] = Escape(arg)
}
return strings.Join(escaped, " ")
}