Add date to redirected file name in windows powershell - powershell

There must be a solution already here, but I can't find it ... what I'd like to do:
Make a link on the windows desktop, double clicking this link will execute a batch.bat and outputs something on stdout and stderr, I'd like to have the output on the console and also in a logfile.
For this part I ended with something like this:
powershell.exe -NoExit C:\mypath\mybatch.bat | tee 2>&1 mylog.log
This does what I want, but I'd like to have the log file named something like mylog-20160317-2125.log
I know that in powershell there's something like [datetime]::now.tostring("yyyyMMdd-HHmm") and Get-Date -f yyyyMMdd-HHmm
But how can I put one or another in my command line above to get the wanted log file name?
Thanks for any help ...

Use something like:
powershell.exe -NoExit C:\mypath\mybatch.bat | tee 2>&1 "mylog-$(Get-Date -f yyyMMdd-HHmm).log"

Related

How to redirect the terminal output of a PowerShell script to a file

I have a script which when it runs, prints out lines to the terminal (with errors). I would like to redirect this output into files.
I read that I should add this line in my PS1 script: ".\myscript.ps1 *> &1 > outfile.log" but it doesn't work because of ampersand character is not allowed.
You don't need space symbol before ampersand.
.\myscript.ps1 *>&1 will redirect all output streams to the stream number 1
.\myscript.ps1 *>outfile.log will redirect all output streams to the file
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-6
If you just want to put your lines into another file from a terminal I would try this:
./myscript.ps1 2>outfile.log
"./" activates the script "2>" takes the stderr stream into (in this case) the outfile.log But I am not sure what you are supposed to do. Maybe if you could post your code or your task here that would be great.
if you want both streams in one outlog, I would do it like that "2>&1"

Powershell fails to run multi-line commands from stdin?

I'm wanting to pass arbitrary scripts to Powershell via stdin.
(In practice, I'd like to avoid having to put the script into a temporary file, but for the purposes of this question I will pipe the contents of a file to powershell.)
So I'm doing something like so (in this example, from a Windows cmd shell):
type myfile.txt | powershell -
It works if myfile.txt contains something like this:
1..3 | % { $_ *2 }
echo done
(It outputs 2\n4\n6\ndone.)
However, if I split this first statement across multiple lines like so, then Powershell simply exists without generating any output at all:
1..3 |
% { $_ *2 }
echo done
This seems to fail for any multiline statement. For example, this also fails to produce output:
1..3 | % {
$_ *2 }
echo done
I'm surprised by this since each are legal Powershell scripts that would work normally if placed into a .ps1 file and run as normal.
I've tried various things including escaping the EOL using line continuation chars, to no avail. The same effect occurs if the parent shell is Powershell, or even Python (using subprocess.Popen with stdin=PIPE). In each case, Powershell exits without any error, and the exit code is 0.
Interestingly, if I run the following, only "before.txt" gets created.
"before" | out-file before.txt
1..3 |
% { $_ *2 }
"after" | out-file after.txt
echo done
Any ideas why Powershell would have trouble reading a multi-line command, if read from stdin?
I'm going to consider this answered by this:
How to end a multi-line command in PowerShell since it shows that an extra newline is required.
However, I'm going to raise this to MS as a bug since this should not be required when reading from a non-tty, or when -NonInteractive switch is specified.
Please vote on my bug report to the Powershell team.
This is not a complete answer, but from what I can tell, the problem has to do with the input being sent in line by line.
To demonstrate the line-by-line issue, I invoke powershell this way:
powershell.exe -command "gc myfile.txt" | powershell.exe -
vs
powershell.exe -command "gc myfile.txt -raw" | powershell.exe -
The first example replicates what you see with type, the second reads the entire contents of the file, and it works as expected.
It also works from within PowerShell if you put the script contents in a string and pipe it into powershell.exe -.
I had a theory that it had to do with line-by-line input lacking line breaks, but it's not so clear cut. If that were the case, why would the first option work but not the second (removing the line break splitting the single pipeline should have no effect, while removing the line break between the pipeline and the echo should make it fail). Maybe there's something unclear about the way powershell is handling the input with or without line breaks.

Compressing to tar.xz using 7-zip through a pipe on windows

My command line is this (powershell):
$7z ="`"c:\Program Files\7-Zip\7z.exe`""
&$7z a -r -ttar -bd -so . | &$7z a -r -txz -bd $archive -si
The produced archive file indeed contains a tar file, but that tar file is corrupt.
Note, that breaking the pipe into two commands works correctly:
&$7z a -r -ttar -bd ${archive}.tmp .
&$7z a -r -txz -bd $archive ${archive}.tmp
The produced archive is perfectly valid.
So, what is wrong with my pipeline?
(I am using Powershell)
Nothing is wrong with your pipeline it is the way that the pipeline works that's causing the error.
PowerShell pipe works in an asynchronous way. Meaning that output of the first command is available to the second command immediately one object at the time even if the first one has not finished executing, See here.
Both Unix and PowerShell pipes operate in the same way. The reason why you might be seeing a difference from Unix to PowerShell is the way in which they go about it is different.
Unix passes Strings between the commands. Where as a Powershell pipe will pass full-fledged .net object between commands. This difference in the data type being past between command will be why it works on unix and not in PowerShell. If 7z.exe can not huddle these .net objects correctly the files will be come corrupt, See here.
Try adding | %{ "$_" } in between the pipes like
&$7z a -r -ttar -bd -so . | %{ "$_" } | &$7z a -r -txz -bd $archive -si
The point is that the second call to 7z expects unmodified data on STDIN, but PowerShell is converting the output from the first call to 7z to (multiple) (string) objects. % is an alias for foreach-object, so what the additional command does is to loop over each object and convert it to a plain string before passing it on to the second call to 7z.
Edit: Reading through PowerShell’s Object Pipeline Corrupts Piped Binary Data it looks to me now as if my suggestion would not work, and there's also no way to fix it. Well, other than wrapping the whole pipeline into a cmd /c "..." call to make cmd and not PowerShell handle the pipeline.
Edit2: I also was trying this solution from the PowerShell Cookbook, but it was very slow.
In the end, I created a .cmd script with the 7z pipes that I'm calling from my PowerShell script.

Calling Patch.exe from Powershell with p0 argument

I'm currently trying to patch some files via PowerShell using Patch.exe
I am able to call the exe using the '&' command, but it doesn't seem to be reading my p0 input. I'm not an expert on PowerShell and any help would be appreciated!
here is what I am calling in PS:
$output = & "$scriptPath\patch.exe" -p0 -i $scriptPath\diff.txt
My error reads:
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
Which I can emulate by leaving out the p0 parameter on my patch file from commandline.
Here are some alternatives I've already tried:
#$output = & "$scriptPath\patch.exe" -p0 -i "$scriptPath\diff.txt"
#CMD /c “$scriptPath\patchFile.bat” (where patchFile.bat has %~dp0patch.exe -p0 < %~dp0diff.txt, seems like powershell reads < as 0<, so there is an error there I think)
#GET-CONTENT $scriptPath\diff.txt | &"$scriptPath\patch.exe" "-p0"
#GET-CONTENT $scriptPath\diff.txt | CMD /c “$scriptPath\patch.exe -p0”
Thanks!
Try:
$output = & "$scriptPath\patch.exe" -p0 -i "$scriptPath\diff.txt"
Patch.exe started in the wrong context and I solved this by using Push-Location / Pop-Location
Here is what my code looks like now
Push-Location $scriptPath
$output = & "$scriptPath\patch.exe" -p0 -i "$scriptPath\diff.txt"
Pop-Location
Keith also mentioned in one of his comments that you can use:
[Environment]::CurrentDirectory = $pwd
I have not tested this, but I assume it does the same thing (Keith is a powershell MVP, I am just a student).

How can I redirect the output of a command (running in a batch loop) to a file?

I have a windows batch file, which iterates over files in a folder and runs a command on each file. Specifically I am running xmllint to validate some files:
for %%i in (c:\temp\*.xml) do (
C:\XMLLINT\xmllint -noout -schema "C:\schemas\schema.xsd" "%%~dpnxi" >> c:\output.txt
)
It currently shows the output on screen. I want to show the output of all these commands placed in an output file. How can I achieve this? By using the append operator (>>) nothing is accomplished except for a blank file being created.
Is it because of xmllint?
If you're trying to redirect error output from the program, it might be writing to stderr. You can try to redirect it with:
for %%i in (c:\temp\*.xml) do (
C:\XMLLINT\xmllint -noout -schema "C:\schemas\schema.xsd" "%%~dpnxi" >> c:\output.txt 2>&1
)
Basically the 2>&1 at the end means redirect anything from stderr (which is 2) to stdout (which is 1). Since stdout is redirected to a file, you should now see the stderr stream in the file. Hope this works for you!
I've never used it, but if its documentation is here, have you tried just removing your "-noout" option, or adding an: "-output c:\output.txt"?