Perl script pauses twice - how do I make it continue without getting carriage returns from the keyboard?
How can I program Perl so that it enters the carriage return for me? Printing a carriage return doesn't work, it just adds an additional line between prompts. At this point I call cakecmd twice, and so to complete my script I have to hit the Enter key twice within my Windows CMD console.
I got a promising response from Perl Beginners Google Group that suggest I use the CPAN Perl Module called Expect, however I am unclear how to use it. How can I tell Perl to use Expect, to look for a no time limit pause and then execute a carriage return?
Thanks
You can leave an optional "tip" with Mahalo's virtual currency, Mahalo Dollars. If you are asking a difficult question that might require some research, or if you'd like a wide variety of feedback, a higher tip often leads to more answers to your question.
M$2 Answers
use IPC::Open2;
my ($rfh, $wfh);
my $pid = open2($rfh, $wrfh, 'cakecmd', 'arg1');
while (my $output = <$rfh>) {
#do whatever you want with cakecmd's output
}
print $wrfh "\n"; #send a carriage return to the cakecmd program
If it's even less complicated than that, if it doesn't actually produce any output you care about, and instead just unzips some file, waits for you to hit enter, and then exits, then your problem is significantly less complicated:
open my $wfh, '|-', 'cakecmd';
print $wfh "\n";
If you really do need Expect because the program is more complicated than that, reply back and we'll walk through the Expect docs (http://search.cpan.org/~rgiersig/Expect-1.21/Expect.pod) to figure it out together.
I'm a Perl instructor.
You can leave an optional "tip" with Mahalo's virtual currency, Mahalo Dollars. If you are asking a difficult question that might require some research, or if you'd like a wide variety of feedback, a higher tip often leads to more answers to your question.
M$\>program < filewithreturns
You can leave an optional "tip" with Mahalo's virtual currency, Mahalo Dollars. If you are asking a difficult question that might require some research, or if you'd like a wide variety of feedback, a higher tip often leads to more answers to your question.
M$
arg. I see now that you had the correct variable, but that Mahalo changed it on you. Please ignore what I said about $ARGV0. You correctly typed $ARGVbracket0bracket, just as I did. I didn't realize Mahalo would consider the brackets to be markup language.
Hi. I actually got it to work. What I'm doing is extracting the word/document.xml file from a Word 2007 file. The new Word 2007 docx format is a zip file made up of at least 8 or so xml files with all the text stored in the word/document.xml file. Yes the word folder is a subfolder within the zip file. Since with your suggestion I was able to get the script to return to the command prompt, I knew I was on the right track. It turns out that I had to get the script to "Sleep" for a second while it unzipped the file. The rest of the script then worked fine.
I have a new further issue that I would like to resolve so I am posting the source code to pastebin.com: http://pastebin.com/f1956533c. Warning: I'm a newbie so there is probably a lot of unnecessary stuff.
My issue is that cakecmd requires the .zip extension whereas the Word 2007 files have the docx extension. So I need to rename the files, adding a .zip extension. I have the code for renaming as you can see. It uses the Win32::OLE module. I got the folder deleter from the same source which works great. This one errors out for me with this message (my .docx file is named gwn.docx): "Renaming gwn.docx to gwn.docx.zip
Can't call method "Rename" on an undefined value at do.pl line 77."
Thanks again for the help
This is a tough one. What is $wfh, a special variable? Also what does the pipe do? Does it pipe the results into $wfh? I need the word/document.xml contents to be set to the variable $content, later in the script, how do I do that. I tried setting $content = $wfg but the command prompt said it was a null variable.
Hi, thanks very much for your answer. It's encouraging to have a Perl instructor answering. I tried:
open my $wfh, '|-', `$unzip extract "$ARGV0" word/document.xml ""`;
print $wfh "\n";
# However it still executed as before with pauses.
Where $unzip = cakecmd.exe and $ARG(0) is the zip file argument in the original perl command.
The original perl script command is:
perl do.pl intro.zip test.txt
Intro.zip is really a Word 2007 file that has had it's extension changed by hand for now. I'm trying to extract the text.
I also tried the original:
open my $wfh, '|-', 'cakecmd';
print $wfh "\n";
# However I got an error: "List form of pipe open not implemented at do.pl line 100."
Here is a link to the script as it is before trying to add a return key input:
http://tinyurl.com/dox2txtmod
I did get a recommendation from someone on Yahoo Answers to use Expect. However no details. I'm also writing to the maker of cakecmd, to turn off the program pause in the next version or have an option too. Thanks again.
99% of my programming is in Unix, so I know almost nothing about the Win32 series of modules.
The error is telling you that the $objWMI->Get() command returned the undefined value. In other words, the Get() failed, and you did not create an object out of the file. I don't know enough about Win32::OLE to help you figure out why that might be. Possible reasons, I imagine, would include an incorrect file name, the file not being in the directory you've given on the previous line, the permissions not being set correctly on the file, or the syntax of the Get() argument being incorrect.
(Speaking of syntax, learn to love interpolation. This argument:
'Cim_Datafile=\'' . $strCurrentFile . '\''
is significantly easier to read as:
"Cim_Datafile='$strCurrentFile'"
or even
qq{Cim_Datafile='$strCurrentFile'}
in my opinion)
Regardless, I don't see any particular reason to go through the hastle of creating Win32::OLE objects and dealing with that module for something as simple as a rename. Perl comes with a built-in rename function:
rename("/root/cimv2/$strCurrentFile", $strNewFile)
or die "Could not rename "/root/cimv2/$strCurrentFile to $strNewFile: $!";
Sorry, I got cut off, here's the code.
{
local $/=undef;
open FILE, "word/document.xml" or die "Couldn't open file: $!";
binmode FILE;
$content = FILE; # Where File should have angled brackets around it but Mahalo is stopping the message at that point.
close FILE;
}
It worked perfectly fine before inserting the code at the beginning which now fixes my one problem and causes another. Thanks though, I think we are moving in the right direction. Is it possible to write the unzipped file to virtual directories or right into variables instead of having them actually write the files?
I'm still not clear on exactly what this unzip command does. Is "word/document.xml" the name of a file that is produced by the unzip command? Or is it the "zipped" file that you're trying to unzip (that seems unlikely, since it ends with .xml instead of .zip)
Also, the "word/document.xml" seems to suggest a file named document.xml within a subdirectory named word. Is that what you actually have after running the unzip command? After the Perl script dies with the error message, can you do a `dir` command and see the word/ sub directory, and `dir word` to see the document.xml within it?
Can you paste your entire code into a site like pastebin.com so we can take a look at exactly what you have?
In your first line, you're trying to combine a pipe-open with back ticks. You can't do that. Back-ticks (the ` quotes) execute the script, just as if you'd written system("$unzip extract...."); except that they return the output. So now you've executed the program, and then you're trying to open a pipe process to a program named by the output of $unzip. You can't do that. Change those backticks to normal double-quotes. And I don't know why you have extra double-quotes around $ARGV0 and around nothing at the end, but they probably don't belong there either.
Did you manually set $ARGV0? Because that's not a built-in Perl variable. The list of command-line arguments is in @ARGV, so the first command line argument is $ARGV0.
The link you posted contains the same error here - using backticks when you should be using double quotes - but even worse has you using an 'exec' to try to run it. exec() executes the given program IN THE CURRENT PROCESS, wiping out anything else the Perl program was going to do. Any code below the exec() is meaningless and will never be done.
The error message you got is a result of Windows not having a decent fork() implementation. Try it with the old two-argument form of open:
open my $wfh, "| $unzip extract $ARGV0 word/document.xml";
print $wfh "\n";
If it turns out that you actually do need all those extra double-quotes you had above for some reason (again, I don't know anything about cakecmd, so I don't know what it's expecting on its command line), make sure you backslash them in your open statement:
open my $wfh, "| $unzip extract \"$ARGV0\" word/document.xml \"\" ";
Excellent this line makes it go back to the command line and clearly induces the unzipping of the right file:
open my $wfh, "| $unzip extract $ARGV0 word/document.xml \"\" " or die "Could not start $unzip: $!";
Now however, my files are no longer read into my variables $content and $_. Instead I get the message: "Couldn't open file: No such file or directory at do.pl line 110." This line is below the lines where the unzipping occurs. It's as if it is being executed first before the unzipping. I'm trying to read in the contents of for instance word/document.xml into my $content variable with this code:
$wfh is not a special variable. It's a new filehandle that you're creating for writing (wfh = Write File Handle).
The pipe tells Perl that this isn't a file you're opening, but a program that you're starting. And it tells Perl that you're going to pipe input to that program.
Add an 'or die $!' to the open line, to make sure that the program is actually starting:
open my $wfh, "| $unzip extract \"$ARGV0\" word/document.xml \"\" " or die "Could not start $unzip: $!";
Getting the contents of the document.xml file into another variable has nothing to do with the problem at hand. After you've sucessfully extracted the file, you can open it like you would any other file in Perl and read its contents.
It's also helpful if you don't paraphrase error messages. There is no Perl message I know of that says "null variable." Please copy and paste the entire error message.