[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

need a sample powershell script which will delete the file older than 3 days

Posted on 2011-10-20
24
Medium Priority
?
888 Views
Last Modified: 2012-05-12
I have file server which keep log data of many applications.
log data will created for many applications.
log data will be created for an application,only if there is any errors get generated.
for each application logs will be generated under specific folders.i.e. each application logs are maintained under separate folder.
so i am looking for a script which will dynamically calculates the date of files under each folder in e: drive and delete log files which are older than 3 days.

I don't to dependent upon schedule task, whenever new files is created and if it finds a files which are older than 3 days in that path, it should delete it immediately.
0
Comment
  • 10
  • 10
  • 4
24 Comments
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37002953
You will need to either have a script which is running all the time (endless loop), or you will ned to create a service (that's running all the time).  Here's a simple script that deletes file in the e:\ drive that are greater than (-gt) 3 days old.

$Files = get-childitem "e:\" -include *.log -recurse | Where {$_.LastWriteTime -gt "3"}
  foreach ($File in $Files) {
    remove-item $File
    write-host "File deleted: $File"
}

Let us know if you want a service or just a loop.
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37003064
i like to ave a service
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37003319
To create a service follow these steps here: http://support.microsoft.com/kb/137890

Then just create the script and put the command in the registry:

"powershell c:\<path to your script>\<script_name>.ps1"
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37008895
there is sometime missing in the script.

Where {$_.LastWriteTime -gt "3"}
it gives a error system.datetime cannot covert the value 3

i trying debug it
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37014425
I am getting below error,
Bad argument to operator '-gt': Could not compare "29-08-2011 22:10:29" to "3". Error: "Cannot convert value "3" to
type "System.DateTime". Error: "String was not recognized as a valid DateTime."".
At line:1 char:83
+ $Files = get-childitem "e:\" -include *.log -recurse | Where {$_.LastWriteTime -gt <<<<  "3"}
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : BadOperatorArgument
 
Bad argument to operator '-gt': Could not compare "29-08-2011 19:53:05" to "3". Error: "Cannot convert value "3" to
type "System.DateTime". Error: "String was not recognized as a valid DateTime."".
At line:1 char:83
+ $Files = get-childitem "e:\" -include *.log -recurse | Where {$_.LastWriteTime -gt <<<<  "3"}
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : BadOperatorArgument
 
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:3 char:16
+     remove-item <<<<  $File
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveIt
   emCommand
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37018232
Oops, date math...try this:

$Files = get-childitem "e:\" -include *.log -recurse | Where {(get_date.Date - $_.LastWriteTime).Days -gt "3"}
  foreach ($File in $Files) {
    remove-item $File
    write-host "File deleted: $File"
}
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37022505
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:4 char:16
+     remove-item <<<<  $File
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveIt
   emCommand

this is error i am getting
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37023900
Then there is no "e:\" drive/path accessible.  Can you change that value or map the drive?
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37023908
Or actually, change the permissions.  Is it deleting any files?  Change the code to this to see what file is failing:

$Files = get-childitem "e:\" -include *.log -recurse | Where {(get_date.Date - $_.LastWriteTime).Days -gt "3"}
  foreach ($File in $Files) {
    write-host "File to be deleted: $File"
    remove-item $File
    }
 
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37029192
no luck!

File deleted:
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:5 char:16
+     remove-item <<<<  $File
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveIt
   emCommand
 
File to be deleted:
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:10 char:16
+     remove-item <<<<  $File
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveIt
   emCommand
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37029194
I also changed to c:\ drive but no luck!
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37041550
It only get the filename and it needs the fullname with the path.  Try:

$Files = get-childitem "e:\" -include *.log -recurse | Where {(get_date.Date - $_.LastWriteTime).Days -gt "3"}
  foreach ($File in $Files) {
    write-host "File to be deleted: $File"
    remove-item $File.fullname
    }
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37043364
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:4 char:16
+     remove-item <<<<  $File.fullname
    + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveIt
   emCommand

issue still persisting
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37047634
What did it print for the "file to be deleted"?  Try deleting the file from the command line with the remove-item command and see if you get the same error.  If so, then it's a permissions thing.
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37050982
i am able to delete the file by remove-item command but not able to delete by script.
this the output i got:

File to be deleted:
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At D:\Documents and Settings\vinod\Desktop\del.ps1:4 char:16
+     remove-item <<<<  $File.fullname

I tried on my local pc, but it gave me the same result.
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37052892
I tried executing $Files = get-childitem "e:\" -include *.txt -recurse | Where {$_.LastWriteTime -gt "3"}
command alone.
and found
The term 'get_date.Date' is not recognized as the name of a cmdlet, function, script file, or operable program. Chec
k the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:81
+ $Files = get-childitem "c:\sccm" -include *.txt -recurse | Where {(get_date.Date <<<<  - $_.LastWriteTime).Days -g
t "3"}
    + CategoryInfo          : ObjectNotFound: (get_date.Date:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
error.

I feel there is some issue with the first staement itself
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 37053069
1. The line you "executed" isn't the line you executed, that is the line doesn't fit to the error message.

2. There are several errors in the line provided by developedtester. It needs to be
$Files = get-childitem "e:\" -include *.log -recurse | Where { ((get-date) - $_.LastWriteTime).Days -gt 3} 

Open in new window

get-date is a commandlet, so it needs to be enclosed in parens if used in an expression. Further, .Days returns an integer, not a string, so comparing it against "3" can result in misbehaviour (ok, not with "3", but imagine you want to use "30" - "4" is greater than that ...).

For many reasons it is usually not a good idea for commands running significantly and/or producing a bigger result set to store them in a var, just to stuff them into foreach. This eats up both time and memory unnecessarily. So I advice to use something like this:
gci "E:\" -include *.log -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % {remove-item $_.FullName -whatIf}

Open in new window

Remove the -whatIf if you want to execute the deletion of files.
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37056881
Thanks for catching those Qlemo.  I agree about stuffing them in a var, but it does make debugging easier, also easier to read, and wouldn't the results of the one pipe get stored temp var in memory till it's all pumped into the next part?  And taking that and putting it in a variable wouldn't really take more memory, eh?  Time yes, but memory?  Anyway, this would should work:

$Files = get-childitem "e:\" -include *.log -recurse | Where {((get-date).Date - $_.LastWriteTime).Days -gt 3}
  foreach ($File in $Files) {
    write-host "File to be deleted: $File"
    remove-item $File.fullname
    }
 
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 37057509
>> wouldn't the results of the one pipe get stored temp var in memory till it's all pumped into the next part
No. There are many cmdlets which can work asynchronously. ForEach-Object is one of them. The piped object stream is processed while it is generated, as we are used by UNIX tools. As soon as a pipe object is processed, it can be dismissed, and memory reused.
Another advantage is that you often can just apply cmdlets on the pipe, and they select what they need from the object by themselves. Remove-Item however needs the file name (or object path) .
0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37060033
Excellent.  Thanks!  So adding printing would be:

gci "E:\" -include *.log -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % { $_.FullName } | % {remove-item $_.FullName -whatIf}

Do you know if it prints the filename and immediately any error message for the "remove" command for that file?  Or does is batch the output/processing so you aren't sure what error the file is for unless it's in the error message because it's not guarenteed to be in order.
0
 
LVL 5

Author Comment

by:VIVEKANANDHAN_PERIASAMY
ID: 37063379
It didn't delete any file and didn't give any output.

So I changed script as
gci "D:\Documents and Settings\vinod\Desktop\hindi"  -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % { $_.FullName } | % {remove-item $_.FullName }

but found below error:
Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
At D:\Documents and Settings\vinod\Desktop\del.ps1:1 char:149
+ gci "D:\Documents and Settings\vinod\Desktop\hindi" -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % {
 $_.FullName } | % {remove-item <<<<  $_.FullName}
0
 
LVL 71

Accepted Solution

by:
Qlemo earned 2000 total points
ID: 37063505
Please review http:#a37053069, which shows the correct commands.
In the last code, using     | % { $_.FullName } | % {remove-item $_.FullName }    is wrong. The first part will put the string stored in $_.FullName into the pipe, and hence the follow-up commands just would need to use that string as $_, not $_.FullName. Tout la phrase:
gci "E:\" -include *.log -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % { $_.FullName } | % {remove-item $_ -whatIf}

Open in new window

To answer to developedtester's question: As you can see the command will not work that way. And it does not print anything. But the buffering and intermixing of command output and errors is an issue if you process the output further, which is not the case here. Errors will be sent out immediately, while the command output might get processed, collected, delayed, reduced, whatever, and then displayed. There might be no connection between an error message and the command output. However, if we force output to be sent to the console with write-host, it is more "synchronous" with error messages. So I guess what you wanted to achieve is:
gci "E:\" -include *.log -recurse | ? { ((get-date) - $_.LastWriteTime).Days -gt 3 } | % { write-host "Processing: " $_.FullName; remove-item $_ -whatIf}

Open in new window

0
 
LVL 16

Expert Comment

by:Bryan Butler
ID: 37064427
Thanks for the explination.  Typically this would be logged.  Is there a "verbose" or another way to do it?  Otherwise for/next would be needed.  Could you at least put a try/catch in for errors?
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 37065051
try/catch is useful if you need to perform special action on error. In this particular case I would refrain from using it - not deleting the files 3 days old now will not harm, next round they might get deleted anyway. Capturing errors here would make the script too complicated, IMHO. I would just log the error messages, nothing more.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The Nano Server Image Builder helps you create a custom Nano Server image and bootable USB media with the aid of a graphical interface. Based on the inputs you provide, it generates images for deployment and creates reusable PowerShell scripts that …
Previously, on our Nano Server Deployment series, we've created a new nano server image and deployed it on a physical server in part 2. Now we will go through configuration.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Screencast - Getting to Know the Pipeline

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question