Showing posts with label problem. Show all posts
Showing posts with label problem. Show all posts

Tuesday, December 18, 2012

Run powershell in windows batch file

I needed to run a powershell script in batch file so it would be executed as one line of commands, without requiring to run .ps1 file directly.
The task is fairly simple, I've done this before. But this time I ran into another problem, because the need of using " signs inside " signs that were actually around -command argument.
This leaded me to a problem that I couldn't use escape chars for " because it would escape it from script altogether.
I couldn't use ' signs either, because that would turn variable names into direct strings.

Here is what I had at start (works within powershell):

$date = Get-Content '.\card_dates.txt' | Select-Object -last 1;
Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) {
   Get-Content $_.FullName | Foreach-Object {
      $_ -replace '#PARAM_1', $date
   } | Set-Content "$($_.FullName).parsed"
}

Here is the modification that gave me the error (if running from batch):

powershell -Command "& { $date = Get-Content '.\card_dates.txt' | Select-Object -last 1; Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) { Get-Content $_.FullName | Foreach-Object {$_ -replace '#PARAM_1', $date} | Set-Content "$($_.FullName).parsed" } } "

This is the error:

Set-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:222
+ ...  | Set-Content $($_.FullName).parsed } }
+                    ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Set-Content], ParameterBinding
   ValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
   icrosoft.PowerShell.Commands.SetContentCommand

So what did I change to make it work?
The solution was actually really simple.
Instead of using:
"$($_.FullName).parsed"

I had to use:
$($($_.FullName) + '.parsed')

And here is the solution that works directly from commandline

powershell -Command "& { $date = Get-Content '.\card_dates.txt' | Select-Object -last 1; Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) { Get-Content $_.FullName | Foreach-Object {$_ -replace '#PARAM_1', $date} | Set-Content $($($_.FullName) + '.parsed') } } "

What this script does?
  1. Read last line from textfile (it is populated there by other scripts)
  2. Read all SQL files inside SQL folder
  3. Withing every file, change #PARAM_1 to be the last line from textfile
  4. Save the file with .parsed extension
Basically we have templates for SQL sentences and historically all the jobs run as BATCH files.
I'm better with Powershell so I wanted to do it in powershell but at the same time keep the old BATCH-es.

Hopefully this information is a bit helpful for you, I spent quite some time to figure out the simple solution.

Wednesday, October 10, 2012

Delete files and folders older than 90 days

A rough start for a blog.

Don't expect for long stories about romantic walks outside or whine about evenings when my dog pooped on the floor.

There you go, some powershell right in your face!

Problem

Folder has tons of items inside and all the files are irrelevant after 90 days.
Irrelevant files need to be deleted.

Solution

I have been using different approaches to do this task. Today my colleague asked for a script that deletes files older than 90 days. Didn't want to give him the "temporary script" I had used before, so I converted it to be oneliner. Here it is:
Get-ChildItem -Path "PUT PATH HERE" -Include "PUT FILTER HERE" -Recurse | where {$_.LastWriteTime -le $(get-date).AddDays(-N)} | Remove-Item
 So you could have it remove all files located in "c:\temp" that have ".txt" extension that have not been updated in past 90 days with the command below:
Get-ChildItem -Path "C:\test" -Include "*.txt" -Recurse | where {$_.LastWriteTime -le $(get-date).AddDays(-90)} | Remove-Item

Conclusion

It is a good idea to remove the last "| Remove-Item" at start and try running it in Console. Review the list of files that would get deleted, if the results get piped to Remove-Item commandlet.


To execute commands as task, you can use the -command parameter for powershell:
-Command "write-host TEST; pause;"
You might want to add these arguments also:
–Noninteractive –Nologo

Read more about running powershell tasks with scheduler from here

Please leave comments if you find this useful or think that this could be achieved in better way.