Golang - 在其中一个部分中执行带空格的命令

时间:2016-08-25 17:31:04

标签: go exec

我正在通过这样调用的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命令在空格上拆分命令,并将其用作字符串数组以传递给exec.Command函数。问题在于它将文件名分成不同的部分,因为filepath需要保持在一起时的空间。即使我正确格式化字符串数组以使filepath在一个部分中,exec.Command仍然会失败,因为有空格。我需要能够执行此脚本以将filepath作为一个带空格的参数。

2 个答案:

答案 0 :(得分:2)

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

cmd.Args之后编辑2-尝试打印cmd := exec.Command("ffprobe", s...)(删除.Output()):

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

这样的事情,找出你的args会发生什么:

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())
}

答案 1 :(得分:0)

好吧,我明白了。

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

我需要从传递给exec.Command函数的arg中删除单引号。