在其中一个部分中使用空格执行命令



我正在通过os/exec包运行这样一个命令:

out, err := Exec("ffprobe -i '/media/Name of File.mp3' -show_entries format=duration -v quiet -of csv=p=0", true, true)

我写的执行命令行调用的函数是:

func Exec(command string, showOutput bool, returnOutput bool) (string, error) {
    log.Println("Running command: " + command)
    lastQuote := rune(0)
    f := func(c rune) bool {
        switch {
        case c == lastQuote:
            lastQuote = rune(0)
            return false
        case lastQuote != rune(0):
            return false
        case unicode.In(c, unicode.Quotation_Mark):
            lastQuote = c
            return false
        default:
            return unicode.IsSpace(c)
        }
    }
    parts := strings.FieldsFunc(command, f)
    //parts = ["ffprobe", "-i", "'/media/Name of File.mp3'", "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"]
    if returnOutput {
        data, err := exec.Command(parts[0], parts[1:]...).Output()
        if err != nil {
            return "", err
        }
        return string(data), nil
    } else {
        cmd := exec.Command(parts[0], parts[1:]...)
        if showOutput {
            cmd.Stderr = os.Stderr
            cmd.Stdout = os.Stdout
        }
        err := cmd.Run()
        if err != nil {
            return "", err
        }
    }
    return "", nil
}

strings.Fields命令在空格上分割命令,并将其用作传递给执行的字符串数组。命令的功能。问题是,由于filepath需要留在一起的空间,它将文件名分割成不同的部分。即使我正确地格式化字符串数组,使filepath在一个部分中,exec.Command仍然失败,因为有一个空格。我需要能够执行这个脚本,以尊重filepath作为一个参数与空格。

  1. 您可以使用strings.Split(s, ":")对特殊字符,如:和切换"与反打勾,
    就像这个工作示例(The Go Playground):
package main
import (
    "fmt"
    "strings"
)
func main() {
    command := `ffprobe : -i "/media/Name of File.mp3" : -show_entries format=duration : -v quiet : -of csv=p=0`
    parts := strings.Split(command, ":")
    for i := 0; i < len(parts); i++ {
        fmt.Println(strings.Trim(parts[i], " "))
    }
}
输出:

ffprobe
-i "/media/Name of File.mp3"
-show_entries format=duration
-v quiet
-of csv=p=0
  • try print cmd.Args after cmd := exec.Command("ffprobe", s...) (remove .Output()):

    for _, v:= range cmd。Args {fmt.Println (v)}

  • 像这样的

    ,来查找你的参数发生了什么:

    s := []string{"-i '/media/Name of File.mp3'", "-show_entries format=duration", "-v quiet", "-of csv=p=0"}
    cmd := exec.Command("ffprobe", s...)
    for _, v := range cmd.Args {
        fmt.Println(v)
    }
    cmd.Args = []string{"ffprobe", "-i '/media/Name of File.mp3'", "-show_entries format=duration", "-v quiet", "-of csv=p=0"}
    fmt.Println()
    for _, v := range cmd.Args {
        fmt.Println(v)
    }
    

    :

    // Command returns the Cmd struct to execute the named program with
    // the given arguments.
    //
    // It sets only the Path and Args in the returned structure.
    //
    // If name contains no path separators, Command uses LookPath to
    // resolve the path to a complete name if possible. Otherwise it uses
    // name directly.
    //
    // The returned Cmd's Args field is constructed from the command name
    // followed by the elements of arg, so arg should not include the
    // command name itself. For example, Command("echo", "hello")
    func Command(name string, arg ...string) *Cmd {
        cmd := &Cmd{
            Path: name,
            Args: append([]string{name}, arg...),
        }
        if filepath.Base(name) == name {
            if lp, err := LookPath(name); err != nil {
                cmd.lookPathErr = err
            } else {
                cmd.Path = lp
            }
        }
        return cmd
    }
    

    编辑3-试试这个

    package main
    import (
        "fmt"
        "os/exec"
    )
    func main() {
        cmd := exec.Command(`ffprobe`, `-i "/media/Name of File.mp3"`, `-show_entries format=duration`, `-v quiet`, `-of csv=p=0`)
        for _, v := range cmd.Args {
            fmt.Println(v)
        }
        fmt.Println(cmd.Run())
    }
    

    我想明白了。

    var parts []string
    preParts := strings.FieldsFunc(command, f)
    for i := range preParts {
        part := preParts[i]
        parts = append(parts, strings.Replace(part, "'", "", -1))
    }
    

    我需要从传入exec的参数中删除单引号。命令功能。