1

I am trying to convert the encoding of the file, but the resulting file does not appear. The command from the console runs correctly.

func main() {
    from := "WINDOWS-1251"
    filename := "3_win1251.csv"
    cmd := exec.Command("iconv", fmt.Sprintf("-f %s", from), fmt.Sprintf("-t UTF-8//TRANSLIT %s", filename), fmt.Sprintf("-o ./convert_%s", filename))
    // command: /usr/bin/iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv
    log.Println(cmd.String())
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }

    log.Println(cmd.ProcessState)
}

result: exit status 0 and the lack of a file.

file: 3_win1251.csv

os: debian 11

  • 4
    try `cmd := exec.Command("iconv", "-f", from, "-t", "UTF-8//TRANSLIT", filename, "-o", fmt.Sprintf("./convert_%s", filename))`. See a similar question here: https://stackoverflow.com/questions/76278028. – Zeke Lu May 24 '23 at 11:20
  • result your command: exit status 1 – Aleksey Budaev May 24 '23 at 11:23
  • 3
    Print the stdout and stderr to see what's wrong. See an example here: https://pkg.go.dev/os/exec@go1.20.4#example-Cmd.CombinedOutput – Zeke Lu May 24 '23 at 11:36
  • @ZekeLu you exec command result err: `iconv: cannot open output file: No such file or directory`. My exec command stderr amd stdout is empty, result code 0. – Aleksey Budaev May 24 '23 at 12:15
  • My money is on this being a matter of the working directory. – Biffen May 24 '23 at 12:29
  • 1
    This one worked for me: https://go.dev/play/p/7ZC9OIW_yhL. The file `3_win1251.csv` is in the same folder as the `main.go` file. And I run the app with `go run .`. – Zeke Lu May 24 '23 at 12:29
  • lol, go run worked for me. Run from GoLand cannot open output file: No such file or directory – Aleksey Budaev May 24 '23 at 13:39

1 Answers1

1

It's worth mentioning that strace is a perfect tool for diagnosing such kind of problems:

$ strace iconv -f WINDOWS-1251 -t UTF-8//TRANSLIT 3_win1251.csv -o ./convert_3_win1251.csv 2>&1 | grep -F execve
execve("/usr/bin/iconv", ["iconv", "-f", "WINDOWS-1251", "-t", "UTF-8//TRANSLIT", "3_win1251.csv", "-o", "./convert_3_win1251.csv"], 0x7fffeed6e768 /* 55 vars */) = 0

Comparing to:

$ strace -f ./main 2>&1 | grep -F execve
execve("./m", ["./m"], 0x7ffd85261008 /* 55 vars */) = 0
[pid 2745776] execve("/usr/bin/iconv", ["iconv", "-f WINDOWS-1251", "-t UTF-8//TRANSLIT 3_win1251.csv", "-o ./convert_3_win1251.csv"], 0xc0001ba000 /* 55 vars */ <unfinished ...>
[pid 2745776] <... execve resumed>)     = 0

It's easy to spot that the arguments are different. Note that the -f option cause it to trace child processes.

While on Windows, we can use the Process Monitor tool. Let's borrow the command from the question exec with double quoted argument.

When running in cmd.exe:

find "SomeText" file.txt

The Command line is find "SomeText" file.txt (see the screenshot below).

Process Create by cmd.exe

But when running with exe.Command, the Command line is find \"SomeText\" file.txt (see the screenshot below). The " are incorrectly escaped. And as suggested by the answer for that question, the solution is to set the whole command line directly.

Process Create by cmd.Command

Zeke Lu
  • 6,349
  • 1
  • 17
  • 23