0

I'm trying to call pdflatex from a guile scheme file. This is the Guile command I'm using:

(system*
 "cat" "foo.txt" "|" "pdflatex" "-jobname" "\"bar\"")

This is the error I get back after running the file:

cat: invalid option -- 'j'
Try 'cat --help' for more information.

If I run the command from bash shell it runs normally.

cat foo.txt | pdflatex -jobname "bar"

-jobname is the correct command for pdflatex, but system* seems to have a problem with it.

I'm using (GNU Guile) 2.2.4 and pdfTeX 3.14159265-2.6-1.40.20.

9716278
  • 2,044
  • 2
  • 14
  • 30
  • 1
    That's not executing a shell command, it's running the `cat` program with everything else as arguments. – Barmar Dec 18 '19 at 21:39
  • 1
    So it doesn't parse shell syntax like `|` to mean piping. – Barmar Dec 18 '19 at 21:41
  • @Barmar I must be miss using `system*` then. I don't suppose there is a way to send a string from scm to pdflatex from scm without using `system*`, that's why I ran into this problem? – 9716278 Dec 18 '19 at 23:05

1 Answers1

0

Use system, not system*. It takes a single string as the argument, and executes it using the shell, which will perform the desired piping.

(system "cat foo.txt | pdflatex -jobname 'bar'")

system* doesn't use the shell. As the manual explains:

system* is similar to system, but accepts only one string per-argument, and performs no shell interpretation. The command is executed using fork and execlp. Accordingly this function may be safer than system in situations where shell interpretation is not required.

Note that your command is a Useless use of cat since pdflatex takes the filename as an argument. You could use system* to execute it directly.

(system* "pdflatex" "-jobname" "bar" "foo.txt")

Also, you don't need to add extra quotes around bar when you use system*; since it doesn't use the shell, it doesn't parse special characters.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • While this can be fine for once-off use, note that using `system` means you not only need to know exactly what the string contains, you also need to know exactly how the shell will interpret it. This is so hard as to be effectively impossible. –  Dec 22 '19 at 08:59
  • @tfb I've added another version of the command that doesn't use the pipe, so can use `system*` and avoid that problem. – Barmar Dec 22 '19 at 20:24
  • I wasn't trying to be nasty about your answer BTW: I think the first answer is fine for cases where you don't have to care: the more general language-in-a-string case is what is so horrible. –  Dec 25 '19 at 13:10
  • If Guile has a way to do the piping in the language instead of invoking the shell, that would be optimal. I don't know Guile well enough. – Barmar Dec 26 '19 at 05:56
  • Neither do I. Although as you point out you don't need a pipe here at all, it's often very hard to be anything like as efficient as pipes are in the shell. There does seem to be some variant of `popen` but if you end up with a stream to which you loop writing bytes then you don't end up being able to do any of the magic that you can do with I/O on modern OSs. –  Dec 26 '19 at 13:48