Dump a log message from tortoise svn to a file using TortoiseProc.exe - perl

I was trying to create a script that could parse the log for a particular revision in svn and get details from that log like the author name, the underlying paths affected and the actions performed. I am trying to use the following command in perl with backticks:
TortoiseProc.exe /command:log /path:"$svn_path" /startrev:"$svn_rev" /endrev:"$svn_rev" /outfile:$file;
for the outfile option it's been specified as /outfile:path\to\file. I've tried so many combinations to get the syntax right but the log file is not getting created. I tried to do
/outfile:D:\other\to\filename.txt
I even tried putting only filename there thinking it'd be created in the same directory, tried only giving the path and even tried creating the file myself waiting for it to write to. Nothing works. Any help would be greatly appreciated.

The backslash in Perl and in most of shells needs to be properly qouted.
Check the cmd.log file and tune the amount of backslashes until it is working
my $file = "D:\\\\other\\\\to\\\\filename.txt";
open my $fh,'>','cmd.log' or die $!;
print $fh "TortoiseProc.exe /command:log /path:\"$svn_path\" /startrev:\"$svn_rev\" /endrev:\"$svn_rev\" /outfile:\"$file\"\r\n";
close($fh);
my $out = `TortoiseProc.exe /command:log /path:"$svn_path" /startrev:"$svn_rev" /endrev:"$svn_rev" /outfile:"$file"`;

The outfile argument only works if you are using a nightly build of TortoiseSVN. See here
An alternative might be to use svn.exe, which also comes with TortoiseSVN, in the following way:
svn.exe log -v -r 111041 >output.txt

Related

How to delete a bunch of lines in perl (adapting a known one-liner)?

context: I'm a beginner in Perl and struggling, please be patient, thanks.
the question: there is a one-liner that seems to do the job I want (in a cygwin console it does fine on my test file). So now I would need to turn it into a script, but I can't manage that unfortunately.
The one-liner in question is provided in the answer by Aki here Delete lines in perl
perl -ne 'print unless /HELLO/../GOODBYE/' <file_name>
Namely I would like to have a script that opens my file "test.dat" and removes the lines between some strings HELLO and GOODBYE. Here is what I tried and which fails (the path is fine for cygwin):
#!/bin/perl
use strict;
use warnings;
open (THEFILE, "+<test.dat") || die "error opening";
my $line;
while ($line =<THEFILE>){
next if /hello/../goodbye/;
print THEFILE $line;
}
close (THEFILE);
Many thanks in advance!
Your one-liner is equivalent to the following
while (<>) {
print unless /HELLO/../GOODBYE/;
}
Your code does something quite different. You should not attempt to read and write to the same file handle, that usually does not do what you think. When you want to quickly edit a file, you can use the -i "in-place edit" switch:
perl -ni -e 'print unless /HELLO/../GOODBYE/' file
Do note that changes to the file are irreversible, so you should make backups. You can use the backup option for that switch, e.g. -i.bak, but be aware that it is not flawless, as running the same command twice will still overwrite your backup (by saving to the same file name twice).
The simplest and safest way to do it, IMO, is to simply use shell redirection
perl script.pl file.txt > newfile.txt
While using the script file I showed at the top.

Unix commands in Perl?

I'm very new to Perl, and I would like to make a program that creates a directory and moves a file into that directory using the Unix command like:
mkdir test
Which I know would make a directory called "test". From there I would like to give more options like:
mv *.jpg test
That would move all .jpg files into my new directory.
So far I have this:
#!/usr/bin/perl
print "Folder Name:";
$fileName = <STDIN>;
chomp($fileType);
$result=`mkdir $fileName`;
print"Your folder was created \n";
Can anyone help me out with this?
Try doing this :
#!/usr/bin/perl
use strict; use warnings;
print "Folder Name:";
$dirName = <STDIN>;
chomp($dirName);
mkdir($dirName) && print "Your folder was created \n";
rename $_, "$dirName/$_" for <*.jpg>;
You will have a better control when using built-in perl functions than using Unix commands. That's the point of my snippet.
Most (if not all) Unix commands have a corresponding version as a function
e.g
mkdir - see here
mv - See here
Etc. either get a print out of the various manual pages (or probably have a trip down to the book shop - O'Reilly nut shell book is quite good along with others).
In perl you can use bash commands in backticks. However, what happens when the directory isn't created by the mkdir command? Your program doesn't get notified of this and continues on its merry way thinking that everything is fine.
You should use built in command in perl that do the same thing.
http://perldoc.perl.org/functions/mkdir.html
http://perldoc.perl.org/functions/rename.html
It is much easier to trap errors with those functions and fail gracefully. In addition, they run faster because you don't have to fork a new process for each command you run.
Perl has some functions similar to those of the shell. You can just use
mkdir $filename;
You can use backquotes to run a shell command, but it is only usefull if the command returns anything to its standard output, which mkdir does not. For commands without output, use system:
0 == system "mv *.jpg $folder" or die "Cannot move: $?";

How to set a crontab job for a perl script

I have a Perl script which I want to run every 4 hours through cron. But somehow it fails to execute through cron and runs fine if I run it through command line. Following is the command which I set in crontab:
perl -q /path_to_script/script.pl > /dev/null
Also, when I run this command on command prompt, it does not execute but when I go in the leaf folder in path_to_script and execute the file, it runs fine.
Also, where will the log files of this cron job be created so that I can view them?
You should probably change the working directory to "leaf folder".
Try this in your crontab command:
cd /path_to_script; perl script.pl >/dev/null
Wrt. log files. Cron will mail you the output. But since you sent stdout to /dev/null, only stderr will be mailed to you.
If you want the output saved in a log file, then pipe the stderr/stdout output of the script into a file, like so:
cd /path_to_script; perl script.pl 2>&1 >my_log_file
Usually cron will send you mail with the output of your program. When you're figuring it out, you probably want to check the environment. It won't necessarily be the same environment as your login shell (since it's not a login shell):
foreach my $key ( keys %ENV ) {
printf "$key: $$ENV{$key}\n";
}
If you're missing something you need, set it in your crontab:
SOME_VAR=some_value
HOME=/Users/Buster
If you need to start in a particular directory, you should chdir there. The starting directory from a cron job probably isn't what you think it is. Without an argument, chdir changes to your home directory. However, sometimes those environment variables might not be set in your cron session, so it's probably better to have a default value:
chdir( $ENV{HOME} || '/Users/Buster' );
At various critical points, you should give error output. This is a good thing even in non-cron programs:
open my $fh, '<', $some_file or die "Didn't find the file I was expecting: $!";
If you redirect things to /dev/null, you lose all that information that might help you solve the problem.
looks like you may have missed the
#!/usr/bin/perl
at the start of your perl script which is why you might need perl -q to run it
once you have added that line you can run it directly from the command line using
/path_to_script/script.pl
If you use a command in your perl program, i advise you to put the full path to the command in your program.
I have try to load environment but it is not more helpful.
After a oversee with one colleague, i think it's from interaction between perl and the system environment.
Best regards,
Moustapha Kourouma

How to grab the Unix command that I had run using Perl script?

As I am still new to Unix and Perl, I'm finding a simple and direct method to grab the Unix command that I had run using Perl script.
What I know is "history" can track back the commands that I had run, but it is not working in Perl using back ticks history to run it.
I tried to put "history > filename" in vi text editor in a temporary file, use command "source" it, and it works, but command "source" also not working in Perl script using back ticks.
Can anyone guide me about my problems? direct me to correct method to solve my problems? T.T
Thanks.
You can't. Shells (well, bash and tcsh, anyway, your shell might, but probably doesn't, vary) only save command history in interactive mode. Commands run in a subshell by a perl script won't be added to the history file.
This will get the history of commands that were run by the user in interactive mode:
$data_file = "~/.bash_history";
open(DAT, $data_file) || die("Could not open file!");
#fileData = <DAT>;
close(DAT);
foreach $command (#fileData) {
# Do things here.
}
As mentioned by Wobble, though, this history file will not include commands run from a Perl script - you'll have to have the script append the command to a file when it runs it, thus creating it's own history file (or, append it to ~/.bash_history, which will have it share the history file with interactive shells).
If you have access to the perl script (that is, you can change it), you can simply write each command run in the perl script to a chosen text file:
sub run_program
{
my $program = shift;
open PROGS, ">>my-commands.txt", or die $!;
print PROGS $program."\n";
`$program`;
close(PROGS);
}
then just run `run_program($command) every time you wish to run a command in the script.

How can I use vim to edit text from Perl while the script is still running?

I have a Perl script that outputs text. I want to import this text into vim, edit it, save it and then exit. On exit, I want the original Perl script to process the edited file.
E.G. how crontab -e works when you add a new job.
Thanks :)
Sounds like a very plain case to use system to run vim on the filename. That will wait until vim is done, at which point you can go ahead and read the file's new contents.
use File::Temp;
my $fh = new File::Temp();
my $fname = $fh->filename;
print $fh "My Text";
$fh->close();
system($ENV{EDITOR}, $fname);
open $fh, '<', $fname or die "Can't open temp file: $!";
while(<$fh>) { print }
close $fh;
A suggestion: Why don't you grab the source to crontab and see what it does?
Other than that, unwind has your answer.
And I think the way to think about this is:
"Okay, I need a program to write out a file, call vim, then do further processing on the file. So, here's my routine to write the file, here's my routine that calls vim (using system), and here's my routine to do the postprocessing after vim is done. Now I'll lace them all together in my main program, and I'm done!"
You seem to want to pipe the output of your script into vim:
script | vim
And then you want the script to somehow know that Vim is finished and resume. That's not how I/O redirection works. The script has no knowledge of what program its output is being piped into.
You mentioned other programs like crontab and cvs; one thing those have in common is that they invoke the editor themselves. They create temporary files, read the EDITOR or VISUAL environment variables (check the manual for details about how they choose which one), run the given program, and wait for the program to finish. Then they continue running and use the file they specified earlier.
Turns out I've done exactly that in Perl. I created a temporary file (with tempfile), wrote a bunch of text into it, and then used system to invoke the editor on the file. You don't even have to close the file while you run the editor.
Pipe the output to vim - and don't forget the dash at the end.
script.pl | vim -
This will open vim with the contents of the scripts output. Just save it :w filename and exit :q. This isn't how crontab -e works, but it comes close enough in an easy way.
Edit:
I missed this part (or maybe the question was edited afterward):
On exit, I want the original Perl
script to process the edited file.
This isn't the best way to do this, but going with my original answer, this works (if you save the file as file.txt):
perl -le 'print "1234"' | vim - && perl -pe '' file.txt
Just replace the perl commands with your perl commands and it should work. Like I said, this is not the best answer, but it should work.