How to pass data to a Shell cmd's stdin?

I am trying to rewrite this shell command:

find -d path | cpio -p dst/

This first invokes the “find” command, which returns a LF-separated list of file paths, which is then fed to cpio, who copies them somewhere else.

I need to use cpio (don’t ask why), but I want to replace the find command with a list I provide myself to cpio.

That means, I have to pass my list to cpio’s stdin channel. But I can’t figure out how to do that with Xojo’s Shell class.

Here’s what I’ve tried:

cpioShell.Mode = 1 // async dim cmd as String = "cd "+src.ShellPath+" ; cpio -p "+dst.Name+"/" cpioShell.Execute (cmd) cpioShell.Write Join (paths, Chr(10))+Chr(10)+chr(4)
The result is that cpio does not seem to accept the data I pass with the Write command, and instead finished as if I had provided an empty list.
I also tried setting Mode to 2, but that didn’t work, either.

If you run cpio in Terminal that way, you’ll see that it waits for input, but with Xojo’s Shell I can’t make that work.

You should probably provide the full path to cpio.

Nope, that’s not the issue. If the path were wrong, cpio would complain, but I don’t get any error msgs in that regard.

in shell script command you are piping the list of files to cpio. in the xojo code, there is no pipe so cpio doesnt get the listing of files.

So, you’re saying that the Shell command is simply missing this rather basic feature of a shell? The other way, getting the output from a command, works with Shell.ReadAll, which is a pipe as well, agreed? So, would it not be logical to assume that Shell.Write would do the same, just in the opposite direction? What is Write for, otherwise? The docs aren’t making much sense to me.

BTW, I found a lame work-around: Write the “input” to a file, and append " </path-to-inputfile" to the command.

in the shell command find <path> <filespec> | cpio <options> there is two seperate commands that are working together. the find command is used to generate the list of files. the cpio command is used to package up the files. The output of the find command is given to the input of the cpio command.

your shell example has the second command (cpio) but it doesnt have any inputs for the listing of files.

your “lame” work around to generate a file with the listing of files and use the option on cpio to read from it, is replacing the find <blah blah blah>| in the original command .

does this make sense?

Scott, I am aware of that all. What I do not understand is why Xojo’s Shell cannot create a pipe from Xojo to the shell when it can create one in the other direction.

In fact, it turns out that even the latter part has now been broken. I did my above tests in Real Studio. There, I was able to read cpio’s ouput in the Shell.DataAvailable event using me.ReadAll. But now, in Xojo 2016, calling ReadAll gives me the same as me.Result, i.e. not the data the cpio pipes out to the console.

This is so utterly broken and useless. Guess I’ll have to do this project in Xcode, after all.

sorry. wish I had better news for you.

No problem, not your fault :slight_smile:

Correction: I was mistaken about recent Xojo versions breaking ReadAll vs. Result. That was a side effect in my testing environent that I did not notice at first.

However, I still cannot send anything to the running shell (which is bash, apparently). I wish, for instance, to send it a crtl-S code to suspend it temporarily. I don’t understand why Shell.Write doesn’t do that. What else is that function good for, then?

Okay, I’ve figured it out. Beatrix pointed me to the solution, which was kind of obvious, in the end: The Examples that come with Xojo include a “Interactive Shell.xojo_binary_project”, which shows how it’s done.

With that, I can now send my data to the cpio command, even send “ctrl-D” to mark the end of input, if I set Shell.Canonical=true.

The only thing I still can’t do is to pause the process as I could in Terminal, by sending ctrl-S. Will see if StackOver has an answer for that.

Turns out calling Shell.Write may lead to app freezes if you are not careful to limit the amount of data you send in one go. E.g, sending 200 bytes seems safe, while sending 7000 bytes is not. There’s a work-around, as shown here: <> and <>