Reputation: 2130
Suppose we have the following directory structure:
~dir00
|-> dir10
| |-> dir20
| |-> file1.txt
|-> dir11
|-> file2.txt
Now, suppose ~dir00 is the current directory. I would have expected the two commands get-childitem * -recurse
andget-childitem -recurse
to produce the same results. However, they do not. The behaviour of the second is what I would expect.
I am trying to write a small library of tools for use with our scripted processes. One tool I need to write is a tool to copy and backup sets of files. I get, as inputs, something that tells me what files/directories/etc. to copy. I have no way of knowing what the user may provide. They may provide a wild-card such as "*", they may provide a file name, they may provide the -recurse parameter, etc. etc. The inputs are fed to get-childitem. The inconsistency of the behaviour of get-childitem when the "path" is just "*" is a big problem. Why does get-childitem suddenly drop the first-level directories when fed a -path of "*" and the -recurse option? (Note that it only drops the first-level directories.) Is there any way I can prevent this odd behaviour?
Now, it gets more bizzare. If we put a file in the root directory, so the file structure becomes
~dir00
|-> dir10
| |-> dir20
| |-> file1.txt
|-> dir11
| |-> file2.txt
|-> file3.txt
then the directories are suddenly NOT dropped. To reproduce this, just execute the following script:
cd $Env:temp
mkdir dir00\dir10\dir20 | out-null
cd dir00
mkdir dir11 | out-null
echo 'hello world 1'>dir10\dir20\file1.txt
echo 'hello world 2'>dir11\file2.txt
$list1 = get-childitem -recurse
echo 'Results of get-childitem -recurse: '
$list1
echo ''
echo 'Number of items:'
$list1.length
echo ''
$list2 = get-childitem * -recurse
echo 'Results of get-childitem * -recurse: '
$list2
echo ''
echo 'Number of items:'
$list2.length
echo ''
echo "hello world 3">file3.txt
$list3 = get-childitem * -recurse
echo 'Results of get-childitem * -recurse: '
$list3
echo ''
echo 'Number of items:'
$list3.length
echo ''
Upvotes: 5
Views: 2724
Reputation: 3419
One possible workaround to this anomalous behaviour would be to substitute the asterisk for a period thereby instructing the Get-ChildItem CMDLet to work with the current directory. Something like this:
$suppliedPath = "*"
if($suppliedPath -eq "*"){
$suppliedPath = $suppliedPath.replace("*", ".")
}
Get-ChildItem $suppliedPath -recurse
Upvotes: 1
Reputation: 13453
This is because the path that you are feeding into Get-ChildItem is different.
When you execute:
Get-ChildItem -Recurse
You are saying the same as:
Get-ChildItem -Path . -Recurse
Or interpreted as: Get Child Item -Path starts at the current directory (dir00)
When you execute:
Get-ChildItem * -Recurse
You are saying, with the *, iterate through all items in the directory, feed those paths to Get-ChildItme, and then Recurse through those items. So the equivalent command that is executed is this:
$items = Get-ChildItem *
Get-ChildItem $items -Recurse
Which works out to:
Get-ChildItem -Path ./dir10 -Recurse
Get-ChildItem -Path ./dir11 -Recurse
Now, what you are seeing is an odd exception (or could be seen as a bug) to this behaviour, and it only happens in this case when you have a root directory that only contains folders and no files. If you create one file in the dir00:
echo 'hello world 1'>test1.txt
And then we execute
Get-ChildItem * -Recurse
It lists exactly the same as Get-ChildItem -Recurse
. So you will only get different results only when you have root directories with no files, only folders.
Upvotes: 8