Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have started using Mathematica to automate file backup operations. The logistics I need make Mathematica a good choice. I am testing and developing the Notebook manually, and Print outputs document the operational events. The saved Notebook provides a record of the process for that day.

I would like to have an easy way to direct Print output to a separate file, for example, by adding

DirectPrintOutputTo["filename "<>DateList["Year","Month","Day"]<>".txt"] 

at the beginning of a Notebook. The advantages of this approach seem obvious. I assume I would need to load my function from a package before calling it. Is something like this this possible? Any suggestions about how to do it?

Alternatively, maybe I could write a print function called PrintTo that would, on first use, open an output file with the name assigned to printToFileName, and I could use the editor to change all the Print functions to PrintTo functions. Not so fancy, but I think I know how to how to do it.

I think that I answered my own question, in the sense that my alternative idea seems straightforward and pretty implementable.

share|improve this question
    
My current scripting approach used Print statements to print results to the scripting notebook. I don't think PutAppend would work (but I may not understand your suggestion). –  George Wolfe Jul 26 '13 at 19:34
    
I have missunderstood the question, I thought you are going to write this not to change Print. So it is not good suggestion then :) –  Kuba Jul 26 '13 at 19:54
2  
Possible duplicates: (5040), (7081), (22584) –  Mr.Wizard Jul 26 '13 at 20:31
    
I wonder if one could use 'TagSet' to make extend the functionality of 'Print' to your specific needs. I don't have much time to think through this now (heading away for a week). May I can work something up later tonight. –  Jagra Jul 27 '13 at 17:30

3 Answers 3

up vote 3 down vote accepted

From the documentation for Print: "Print sends its output to the channel $Output."

Therefore you can just do this:

$Output = OpenWrite["filename " <> DateList["Year", "Month", "Day"] <> ".txt"];

before you run the file.

Something more structured would be like this:

stream = OpenWrite["c:/users/gre/desktop/derp.txt"];
AppendTo[$Output, stream];

(* run your file here *)

Close[stream];
$Output = Most[$Output];

Since Print by default outputs to stdout, you could also pipe the output by running the notebook as a script.

share|improve this answer
    
I tried using Block[{$Output = ..., but this didn't seem to work for $Output. –  amr Jul 26 '13 at 20:20
    
Beat me to the punch about $Output. However, I was working on a generic environment. –  rcollyer Jul 26 '13 at 20:21
    
@rcollyer Well you both beat me, so... –  Mr.Wizard Jul 26 '13 at 20:23
    
@rcollyer agreed. usually i go the lazy route :D –  amr Jul 26 '13 at 20:23
3  
@Mr.Wizard I beat both of you a long time ago, and Leonid. :) –  rcollyer Jul 26 '13 at 20:24

I don't recommend modifying Print to redirect the output when it is not necessary. Instead, you can build up a custom solution that suits your needs. I use a variant of the following for logging in my projects and you should be able to tweak them to your application.

Clear[logFile, writeLog, showLog];
logFile := "project-" <> DateString[##, {"Year", "Month", "Day"}] <> ".log" &;

writeLog[message_String] := 
    Module[{str = OpenAppend[logFile[]], date = DateString[]}, 
        WriteString[str, StringJoin @@ Riffle[{date, message, "\n"}, "\t"]];
        Close[str];
    ]

showLog := FilePrint@logFile@## &;
clearLog := Module[{str = OpenWrite[logFile@##]}, Close@str;] &

Note the use of OpenAppend and OpenWrite in the above functions. OpenAppend creates a new file if none exists, but appends to an already existing file. OpenWrite, on the other hand, simply creates a new empty file regardless of whether a file already exists with that name (thus erasing data, which is what we want here).

Since writeLog just takes a string as input, you can simply replace your Print commands with writeLog and it should work fine.

logFile[]
(* "project-20130726.log" *)

writeLog["Hello world"];
showLog[]
(* Fri 26 Jul 2013 12:51:31 Hello world *)

clearLog[]
showLog[]
(* crickets *)
share|improve this answer

This is already built-in; Print directs all output to the $Output channel where a channel is just a list of open streams. So, to redirect it, simply

oldout = $Output;
    strm = OpenAppend["filename "<>DateString[]<>".txt"];    
    $Output = {strm};

and to switch it back

$Output = oldout;
Close[strm];

Assuming you just want an environment where Print is re-directed, you could do something like this

ClearAll[RedirectPrint];
SetAttributes[RedirectPrint, HoldRest];
Options[RedirectPrint] = {OpenMethod -> OpenAppend};
RedirectPrint[filename_String, body_, opts:OptionsPattern[]] :=
 Block[{old, strm, open},
  open = OptionValue[OpenMethod]; (* needs error checking here *)
  old = $Output;
      Internal`WithLocalSettings[
        strm = open[filename];
        $Output = {strm},
    body,
    $Output = old;
    Close[strm]
  ]
 ]
share|improve this answer
    
@Mike the change is good, I was taking the OP's code directly without looking at it ... –  rcollyer Jul 28 '13 at 3:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.