views:

809

answers:

3

I'm just learning PowerShell and I've written a script that will be used for archiving log files from a server. I'm in pretty good shape with everything but the recursiveness or not of get-childitem...

The issue I seem to be having is that when Get-ChildItem is not recursive and -Include is present with only one filter, it is ignored! Or, I'm doing something wrong (likely).

I've cleaned up the output a little...

PS C:\foo> Get-childitem -path "c:\foo"

Name
----
bar1.doc
bar2.doc
bar3.doc
foo1.txt
foo2.txt
foo3.txt

PS C:\foo> Get-childitem -path "c:\foo" -Include *.txt
PS C:\foo> Get-childitem -path "c:\foo" -Include *.txt -recurse

Name
----
foo1.txt
foo2.txt
foo3.txt

Sooo??? I had a fantasy where all I had to do was branch to a path of the script that did not have the recurse switch. (By the way, is it possible to variably apply parameters so as to avoid duplicated code paths where the only variability is the parameters to a cmdlet?)

Anyway, here is my script for completeness, in addition to my issue with get-childitem, any feedback is appreciated.

Thanks, Ben

function MoveFiles()
{
 Get-ChildItem -Path $source -Recurse -Include $ext | where { $_.LastWriteTime -lt (Get-Date).AddDays(-$days) } | foreach {
  $SourceDirectory = $_.DirectoryName;
  $SourceFile = $_.FullName;
  $DestinationDirectory = $SourceDirectory -replace [regex]::Escape($source), $dest;
  $DestionationFile = $SourceFile -replace [regex]::Escape($source), $dest;

  if ($WhatIf){
   #Write-Host $SourceDirectory;
   #Write-Host $DestinationDirectory;
   Write-Host $SourceFile -NoNewline
   Write-Host " moved to " -NoNewline
   Write-Host $DestionationFile;
  }else{
   if ($DestinationDirectory)
   {
    if ( -not [System.IO.Directory]::Exists($DestinationDirectory)) {
     [void](New-Item $DestinationDirectory -ItemType directory -Force);
    }

    Move-Item -Path $SourceFile -Destination $DestionationFile -Force;
   }
  }
 }
}
+1  A: 

I can't tell you the exact why of it (but I will keep looking), but the behavior is codumented in the Get-Help for Get-ChildItem:

-Include <string[]>
    Retrieves only the specified items. The value of this parameter qualifies the Path parameter. Enter a path elem
    ent or pattern, such as "*.txt". Wildcards are permitted.

    The Include parameter is effective only when the command includes the Recurse parameter or the path leads to th
    e contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the C:\
    Windows directory.
EBGreen
+3  A: 

The answer is in the full description of the command (get-help get-childitem -full):

The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the C:\Windows directory.

So the following would work without recurse.

PS C:\foo> Get-childitem -path "c:\foo\*" -Include *.txt
hythlodayr
I feel like a total idiot! Thanks for your help.
Ben
Nah. Blame MS for making this command too finicky.
hythlodayr
Basically, Path and Recurse determine your initial list of objects, then those are filtered by Include and Exclude. So "C:\foo" would give you one directory info object. "C:\foo\*" would give you all the contents of "foo".
JasonMArcher
+2  A: 

This is expected behaviour, but admittedly confusing. From the Get-ChildItem help file:

-Include <string[]>

Retrieves only the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as "*.txt". Wildcards are permitted.

The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows*, where the wildcard character specifies the contents of the C:\ Windows directory.

ps> help dir -full | more

Hope this helps,

-Oisin

x0n