Powershell v2 files deletion error Cannot convert the "LastWriteTime" - powershell

OS : Windows 2008 R2 64bit
I am trying to delete all txt files older then X days using powershell using below CMD
PS C:\temp> POWERSHELL -COMMAND "Get-ChildItem c:\temp -Recurse -Include *.txt | Where LastWriteTime -lt (Get-Date).AddDays(-10) | Remove-Item -Force"
But getting following error
Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "LastWriteTime" value of type "System.String" to type "System.Management.Automation.ScriptBlock".At line:1 char:54+ Get-ChildItem c:\temp -Recurse -Include *.txt | Where <<<< LastWriteTime -lt (Get-Date).AddDays(-10) | Remove-Item -Force + CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand
PS version:
PS C:\temp> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
Howto sort it?

???.... and you can use PowerShell directly to execute as much code, .ps1 files, and functions as you choose in a single run. No need for separate code runs and you don't need cmd.exe for that, though you can if you choose to.
Since PowerShell is doing the function run (the work) anyways, and code/these functions are PowerShell code (assuming here), then again, just put that is a single .ps1 file and run it directly
# Contents of SomeName.ps1 file
Get-ChildItem -path (c:\temp -Recurse -Include *.txt).FullName |
ForEach {
$PSItem|
Where LastWriteTime -lt (Get-Date).AddDays(-10) |
Remove-Item -Force
}
powershell '.\SomeName.ps1'

Related

Need to list all new files in directory with Powershell

I have to create a list of all latest or accessed files in a directory in .csv format. However my current script doesn't output a useful file. (always 0KB)
Get-ChildItem -Path X:\ -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object { Get-ChildItem $_.Name -Recurse |
select Name, *time |
Sort-Object -Property LastAccessTime -Descending |
Select-Object -First 1 } |
Export-Csv -Path C:\...\testfile.csv
Does anyone have a better idea?
EDIT: The errors look like this:
+ CategoryInfo : ReadError: (X:\xxx:String) [Get-ChildItem], DirectoryNotFoundException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
That code might generate some errors if you don't cd to X:\ before running it. You can remediate that with changing:
# this
Get-ChildItem $_.Name -Recurse
# to this
Get-ChildItem $_.FullName -Recurse
Then it always uses absolute path rather than relative one.
NOTE: as #mklement0 pointed out in the comments, it's worth noting that in PowerShell 6 and higher the same can be achieved by using the object directly (no need to use .FullName property).
Here's his helpful answer explaining it in details - really worth reading!

Is it possible to filter using Get-ChildItem -Name?

In one of the questions I answered recently I found interesting answer which shouldn't be working but still was. The question was about how to find specific folder recursively by its name and cd to it.
The answer proposed by A guest who's called Redd was:
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
As per the documentation of Get-ChildItem, -Name parameter is supposed to be SwitchParameter type and is responsible for returning only name (System.String), instead of System.Object.
How it's possible that the solution still works?
MCVE:
# cd C:\SO\56628221
mkdir test, test1, test2, test3
mkdir .\test2\folder
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
Current output:
test2\folder
Expected output:
Get-ChildItem : A positional parameter cannot be found that accepts argument 'Folder'.
What have I tried?
First I checked that -Path is the only positional parameter. Apparently it is:
All the other params have Position: Named.
Then I tried to switch the arguments to something like this:
Get-ChildItem -Path .\ Folder -Name -Recurse -Depth 10
It was still working, so that was clear indication that what I'm passing to the cmdlet is not the value for -Name.
Last thing I supposed was that I just send array of strings to -Path. I tried to do this explicitely:
[string[]]$a = '.\','Folder'
$a.GetType()
Get-ChildItem -Path $a -Name -Recurse -Depth 10
# Output:
PS C:\SO\56628221> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String[] System.Array
PS C:\SO\56628221> Get-ChildItem -Path $a -Name -Recurse -Depth 10
test
test1
test2
test3
test2\folder
Get-ChildItem : Cannot find path 'C:\SO\56628221\Folder' because it does not exist.
At line:1 char:1
+ Get-ChildItem -Path $a -Name -Recurse -Depth 10
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\SO\56628221\Folder:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
tl;dr:
Apparently there's an incorrect information in current version of Get-ChildItem documentation, stating that -Filter is no longer positional.
The above is no longer true, it's been fixed in this PR.
Long answer:
In fact, the value 'Folder' is being passed to -Filter parameter. Even though PowerShell 6 documentation says opposite, -Filter is a positional parameter. By mistake, that change was introduced in PowerShell v6+ while PowerShell 5.1 help article for Get-ChildItem is still correct.
The cmdlet you run:
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
is effectively:
Get-ChildItem -Path ".\" -Name -Filter "Folder" -Recurse -Depth 10
Even though -Filter parameter in Get-ChildItem might be tricky in usage, in that case it works perfectly and the filter is applied to only show items named 'Folder'. As that invocation doesn't specify -File or -Directory, if you run:
# Create new file named 'Folder'
New-Item Folder
and then run the cmdlet once again, it'd return both file and folder which was created:
PS C:\SO\56628221> Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
Folder
test2\folder
The output is exactly the same if you explicitely use -Filter:
PS C:\SO\56628221> Get-ChildItem -Path .\ -Name -Filter Folder -Recurse -Depth 10
Folder
test2\folder

How can I use the -last parameter in PowerShell to select files to copy?

Each day we create copies of the production databases that users then copy from the server to their local machines. I want to automate this process with a script that will select the last three files in a particular path and copy them.
I can use
dir $HS3BackupPath | sort LastWriteTime | select -last 3
to properly select and display the three files I want to copy, but I've been unsuccessful in piping the results of this to a copy command.
After looking at this question, this question and this one, I tried
dir $HS3BackupPath | sort LastWriteTime | select -last 3 |
copy-item $HS3BackupPath $Dest
and got this error:
copy-item : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
At C:\scripts\RefreshHS3.ps1:96 char:63
+ dir $HS3BackupPath | sort LastWriteTime |select -last 3 | copy-item $HS3Back ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (HS3PREcompress-...11-38-17-62.mdb:PSObject) [Copy-Item], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.CopyItemCommand
Trying variations, I'm here now
Copy-Item $HS3BackupPath $Dest | sort LastWriteTime | select -last 3
and getting this error:
Copy-Item : Container cannot be copied onto existing leaf item.
At C:\scripts\RefreshHS3.ps1:98 char:1
+ Copy-Item $HS3BackupPath $Dest | sort LastWriteTime | select -last 3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (\\DC1\HS3_db_Backups\:String) [Copy-Item], PSArgumentException
+ FullyQualifiedErrorId : CopyContainerItemToLeafError,Microsoft.PowerShell.Commands.CopyItemCommand
Anyone know the proper syntax to copy these files appropriately?
dir $HS3BackupPath | sort LastWriteTime | select -last 3 | ForEach-Object{ copy-item $_.FullName $Dest}
The input object for Copy-Item is the issue. One way around it is to use a ForEach-Object and use the FullName property as the Path for Copy-Item
Like Ansgar says you can just pipe directly into Copy-Item as well as long as you use the named parameter -Destination
dir $HS3BackupPath | sort LastWriteTime | select -last 3 | Copy-Item -Destination $Dest
Copy-Item only has space for 2 positional paramenters for -Path and -Destination. In your example those were specified leaving no space for the pipeline input. Removing the -Path allowed the pipeline input to match. To make sure there were no positional conflicts -Destination needed to be named.

How to recursively search a directory for all files including hidden files in hidden directories, with PowerShell?

To recursively search for a hidden file, I am using:
gci -Path C:\ -Filter part_of_filename* -Recurse -Force | where { $_.Attributes -match "Hidden"}
The output shows me many errors exactly like this (depending on the path):
Get-ChildItem : Access to the path 'C:\Documents and Settings' is
denied. At
C:\Users\USERNAME\Documents\powershell\searchdisk.ps1:10
char:5
+ gci <<<< -Path C:\ -Filter part_of_filename* -Recurse -Force | where { $_.Attributes -match "Hidden"}
+ CategoryInfo : PermissionDenied: (C:\Documents and Settings:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
I need a PowerShell command that recursively searches ANY directory including hidden directories and shows me all files including hidden files of the name part_of_filename* (for this example)
I ran the command using PowerShell ISE as Administrator. It won't search inside directories like
C:\Windows\System32\LogFiles\WMI\RtBackup
You're doing it right. Just run it in an elevated console and remove the filter. If you don't care about permission errors, append -ErrorAction SilentlyContinue:
Get-ChildItem -Path C:\ -Filter lush* -Recurse -Force `
-ErrorAction SilentlyContinue
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-arhs 25.09.2013 12:16 1208 lush.asx
lush.asx has the ReadOnly, Hidden and System attributes.
You may also want to pipe to | select Name, Length, Directory to get rid of that unfortunate Directory: C:\ line. There's also a DirectoryName if you want the full path without the filename.

Parsing Shortcuts in Powershell

I have some code which is trying to make a copy of a directory which contains shortcuts:
# Create a directory to store the files in
mkdir "D:\backup-temp\website.com files\"
# Search for shortcuts so that we can exclude them from the copy
$DirLinks = Get-ChildItem "\\web1\c$\Web Sites\website\" -Recurse | ? { $_.Attributes -like "*ReparsePoint*" } | % { $_.FullName }
# Execute the copy
cp -recurse -Exclude $DirLinks "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
But when I execute the script I get the following error:
Copy-Item : The symbolic link cannot be followed because its type is disabled.
At C:\scripts\backup.ps1:16 char:3
+ cp <<<< -recurse "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId :
System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
It seems the script is getting hung up on a symbolic link (I'm assuming the shortcut) that I'm trying to exclude in the fourth line of the script.
How can I tell powershell to ignore/exclude shortcuts?
Thanks,
Brad
If you are on V3 or higher you can eliminate the reparse points like so:
Get-ChildItem "\\web1\c$\Web Sites\website" -Recurse -Attributes !ReparsePoint |
Copy-Item -Dest "D:\backup-temp\website.com files"
On V1/V2 you can do this:
Get-ChildItem "\\web1\c$\Web Sites\website" |
Where {!($_.Attributes -bor [IO.FileAttributes]::ReparsePoint)} |
Copy-Item -Dest "D:\backup-temp\website.com files" -Recurse
So it turns out that the issue I faces is explained in this Microsoft Blog Post:
http://blogs.msdn.com/b/junfeng/archive/2012/05/07/the-symbolic-link-cannot-be-followed-because-its-type-is-disabled.aspx
Essentially on the server I am running the powershell script from I needed to run the following command:
fsutil behavior set SymlinkEvaluation R2R:1
This allows Remote to remote symbolic links. Once this is in place the above powershell commands run as expected without errors.