我正在通过这样调用的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
作为一个带空格的参数。
答案 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中删除单引号。