Powershell network drive Get-ChildItem issues

Essentially I’m trying to use PowerShell to find files with certain file extensions on a network drive created on or after June 1st of this year. I thought I could do that with the following statement:

Get-ChildItem NETWORKPATH*.* -recurse -include *.xlsx | Where-Object { $_.CreationTime -ge “06/01/2014” }

I run into 2 problems:

  1. The command only returns files from the root and one folder on the network drive, there’s over 100 folders on this network drive
  2. The command returns 3 out of the 5 files created after 6/1/14 and one created well before my creation time date.

I have access to all of the folders on the network drive. When I run Windows 7 search it finds all of the files. It doesn’t matter if I run Powershell as administrator or not. It doesn’t matter if I run it from my machine (Windows 7) or from one of our 2008 servers. The network drive I’m trying to search through is on a 2003 file server. What am I doing wrong?

Any help is appreciated.

Do you get all of the files if you execute the following code:

Get-ChildItem -Path NETWORKPATH -Recurse -Force

Or do you still only get some of the files?

First, I would remove “*.*” at the end of NETWORKPATH.

Second, are sure you have access to all the shares and all the subfolders in \NETWORKPATH\ ?

Also, if you pipe the first part of your command to Get-Member, you will see that the property CreationTime should be a DateTime object :

Get-ChildItem NETWORKPATH -recurse -include *.xlsx | Get-Member -Name CreationTime

   TypeName: System.IO.FileInfo

Name         MemberType Definition

CreationTime Property   System.DateTime CreationTime {get;set;} 

To make sure that your date is considered as a DateTime object, instead of a string, you can do this :

 Get-ChildItem NETWORKPATH -recurse -include *.xlsx | Where-Object { $_.CreationTime -ge ("06/01/2014" -as [DateTime] ) } 

One word of caution : (“06/01/2014” -as [DateTime] ) can be interpreted differently , depending on your $PSCulture.
For me, it was interpreted as 6th of January , not 1st of June, because my $PSCulture is English Ireland :

 $date2 = ("06/01/2014" -as [DateTime])
$date2

06 January 2014 00:00:00


$PSCulture
en-IE 

If you don’t like this behaviour, you can do it another way :

 [DateTime]$date3 = "06/01/2014"
$date3

01 June 2014 00:00:00 

Does the Windows 2003 file server have PowerShell installed? I’m sure you can make this work the way you’re trying, but it’s going to be inefficient. How inefficient depends on how many xlsx files reside in that location because the command will retrieve a list of all the xlsx files and perform the filtering on the local computer. The better option would be to install PowerShell version 2 on the Windows 2003 file server, enable PowerShell remoting and take advantage of PowerShell remoting by placing the Get-ChildItem command inside of the script block of Invoke-Command. That way all of the filtering is done at the source machine and you’ll only pull the results across the network.

Invoke-Command -ComputerName FileServerName {
    Get-ChildItem -Path LOCALPATH\*.xlsx -Recurse |
    Where-Object {$_.CreationTime -ge '06/01/2014'}
}

@Alexander the -force option doesn’t change the results

@Mathieu removing . causes the whole command to return nothing. Additionally, I’ve run this command as an admin and not as an admin under my own account and under a network admin account with no difference in result. I know my account can at least access all the folders (certainly more than just the root and one random subfolder) and the network admin account can access anything on the network. That being said, issue #2 is a non-issue now since I found out some network files will have a creation date newer than their modified date if they’ve been copied from another location.

@Mike I can certainly try to install PowerShell on my 2003 server, but it will be a major inconvenience if that requires a restart. Additionally, do you think running it locally will return more results? My problem right now isn’t that it takes a long time to run the command, it’s that it only returns results for the root of the folder and one folder out of at least 100.

Try this:

Get-ChildItem -Path NETWORKPATH\*.xlsx -Recurse |
Where-Object {$_.CreationTime -ge '06/01/2014'}

@Mike, this gives me the same result whether I put in the -Recurse option or not. It only shows me the xlsx files in the root that match the creationtime parameters

gci -path PATH -recurse | where {$_.extension -match “xlsx”}
OR
gci PATH**.xlsx -recurse

This is what you are missing. If you define the file extension in the get-child item it is only displaying results from within that container regardless if you put recurse. You need to through in a wildcard for possible subfolders as well.

I assume that you’re using PowerShell 2.0. The behavior of Get-ChildItem is quite different on current versions. What worked for me in testing (on PowerShell 2.0) was to remove the *.* portion of the path from your original command:

Get-ChildItem NETWORKPATH -Recurse -Include *.xlsx | Where-Object { $_.CreationTime -ge "06/01/2014" }

Agreed. I was way off. Dave’s text returns the correct contents of both the named directory as well as the subdirectories.

gci -path PATH -recurse | where {$_.extension -match “xlsx”} was the silver bullet to all of this. Thanks for everyone’s help, double thanks to Robert for the answer. As this script has already been running for an hour I’m going to file Mike’s lead and try to install Powershell on the actual file server.

Not sure if I need to start a new topic but I took Mike’s advice to invoke the code remotely, now I’m having an issue with multiple -and -or statements.

PS H:> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object {{ $.e
xtension-match “xls” -or $
.extension-match “xlk” } -and { $_.creationtime -ge “06/01/2014”}}

Above is my code example. What I’m trying to do is remotely run this powershell code on my file server and have it return all xls and xlk files with a creation date on or later than 6/1/2014. When I run this code it starts spitting out all of the folders in that remote location. If I only compare two things like so:

PS H:> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object { $.extension-match “xls” -and $.creationtime -ge “06/01/2014”}

Only the xls files created on or after that date display. What’s going on here? Do I need to use something other than nest -and -or statements? Any help is appreciated.

I’ll note that breaking the “where” statements up didn’t work either. I would run a command like:

PS H:\> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object { $_.extension-match "xls" -or $_.extension-match "xlk" } | where-object { $_.creationtime -ge "06/01/2014"}

And I’d get xlsx values returned which definitely not what I wanted.

Using parenthesis didn’t work either, see the example below:

PS H:\> Invoke-Command -computername owlnas2 { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object {( $_.extension-match "xls" -or $_.extension-match "xlk") -and $_.creationtime -ge "06/01/2014"}

Clarification, using parenthesis gave me the same result as splitting up my “where” statements. I’m searching for xls and xlk files and getting xlsx files in my results.

You’re using a -match operator, which takes a regular expression. Any string which contains “xls” will return true when you say $someString -match ‘xls’. There are a few ways you could change this code to work the way you like, mainly depending on your personal preference, performance requirements, and how you think it might change in the future.

# Using an array of acceptable extensions.  Don't forget the period; it's part of the extension, as far as .NET is concerned.
# Still using Where-Object (which may not perform as well)

$extensionsToMatch = '.xls', '.xlsk'
Get-ChildItem -Recurse | Where-Object { $extensionsToMatch -contains $_.Extension }

# Using an array again, but this time passed to the -Include parameter of Get-ChildItem.  Should perform better than Where-Object.
# This time, we need to add a * wildcard before the extensions in the array
$extensionsToMatch = '*.xls', '*.xlsk'

Get-ChildItem -Recurse -Include $extensionsToMatch