Discussion:
square brackets, filenames, get-acl, get-item:solved (almost)
(too old to reply)
Whisperer
2007-03-27 13:55:06 UTC
Permalink
After reading around about square brackets in names of files I can
understand
the need for using escape characters when referring to such files but
the comments I have found always assume the string for the file name
is
entered manually.
This is no use when the filename is retrieved programmatically e.g.
elsewhere in a script

Also various comments refer to using single quotation marks around
strings to
stop powershell interpreting wildcard characters.
I have been unable to get this working, specifically when using the
get-item or get-acl commands
(PERHAPS someone can me an example to try on my machine)
Even if I could get it working I again see potential problems when the
filename string is retrieved programmatically.
(PERHAPS again someone can me an example to try on my machine)

Another suggestion which I have read is to use the parameter
-LiteralPath
This is suggested when using get-childitem.
This parameter is not an option on my Powershell and neither is it an
option for get-item and get-acl.

AM I on the right version of Powershell? I have version 1.0.9567.0
according to Add-Remove Programs.

In frustration I have been performing tests and think I have cracked
it.
Trying to explain what I have found is not easy but I have tried my
best!
The following text takes you step-by-step through what I did and what I
found.
I think this is the clearest way I can come up with.


Create a folder with one file in called test[1].txt

From that folder enter the following command:
$a=(get-item *).name
This sets $a to be the string test[1].txt

Enter the following command:
get-acl *
This returns the following error:
Cannot find path 'test[1].sfx' because it does not exist.
The command is interpreting the [] as wildcards - see Follow up
exercise below (at end)

Now enter the following command:
get-acl $a
This produces no output as it is interpreting the [] in $a as wildcards
and hence
the command is actually looking for a file named test1.txt - see Follow
up exercise below (at end)

To get the required results the [ and ] characters in the name returned
by
get-item need escaping to stop them being interpreted as wildcards.
This can be done by using the string method .replace to insert escape
characters i.e.`
You might think the form would be .replace("[","`[") except this will
not work
In the first instance, powershell checks for wildcards in the first
parameter of the replace so
the first [ in this command is interpreted as a wildcard - which is
meaningless as there is no ] to pair with it
The form .replace("`[","`[") is correct in the first parameter i.e. it
will search for instances of [ but
the form fails because the `[ in the second parameter is interpreted as
an escaped [ so the replacement string is
simply [ i.e. this form replaces [ with [ - nothing changes
NOTE the second parameter does not interpret [ or ] as a wildcard so
using a single ` is
no different to having no ` at all
The form .replace("`[","``[") works because the double backtick `` in
the second parameter is treated as
an escaped backtick and the [ is not treated as a wildcard in the
second parameter so
the resultant replacement string is `[

So to replace all instances of [ or ] with `[ or `] the complete form
is:
.replace("`[","``[").replace("`]","``]")

So for the get-acl command above the correct form is:
get-acl ((get-item *).name.replace("`[","``[").replace("`]","``]"))

Also....
The following form does not work - haven't got my head round why:
get-acl ((get-item
*).name.replace("`[","````[").replace("`]","````]"))

and the following form does work - but again I haven't got my head
round why:
get-acl ((get-item
*).name.replace("`[","``````[").replace("`]","``````]"))


There must be a better way than this....
Again any example of how to do all this using snigle quotation marks
would be
appreciated - particularly when done inside a script or over two
command line entries
e.g. a working example of the following (where again the get-acl
command produces no output)
$a='test[1].txt'
get-acl $a


Follow up exercise

Create a file called test1.txt in the test folder
i.e. the folder now contains test[1].txt and test1.txt
From the folder run the following command:
get-item *
The output produced shows 2 entries as expected:
Name
----
test1.txt
test[1].txt

Now enter the following command:
get-acl *
The output produced shows 2 entries which are not as expected:
Path
----
test1.txt
test1.txt
The get-acl command is interpreting the wildcards in the strings
returned from the expansion of
the * wildcard.
Further investigations (by tweeking permissions) show that get-acl is
returning 2 instances of
the exact same file object.
--
Whisperer
Whisperer
2007-03-27 15:37:01 UTC
Permalink
The previous post is correct - for the command line.
The testing was done at the command line but when I came to put it in
script I found I had to use the form with 6 backticks in the secon
replace parameter.
See script below
Note the two different ways the scripts tests for passing the filenam
string to get-acl

PS C:\test> get-content .\test.ps1
$testpath="c:\test\*"
get-item $testpath | foreach {

$objectinfo=$_
$acl1=(get-ac
$objectinfo.fullname.replace("`[","``````[").replace("`]","``````]"))

$acl2=($objectinfo.fullname.replace("`[","``````[").replace("`]","``````]")|get-acl)
$itemaccesses=$acl1.access
$owner=$acl2.owner
write-host "object:"$objectinfo.fullname
write-host "Owner:"$owner
foreach ($access in $itemaccesses) { write-hos
"User:"$access.identityreference
write-hos
"Rights:"$access.filesystemrights
}


--
Whisperer
Whisperer
2007-03-27 15:55:38 UTC
Permalink
Ignore the second post.
I think my brain has given up trying to work this out.
The script given in the second post works fine with just 2 backticks in
place of the 6.
--
Whisperer
Lee Holmes [MSFT]
2007-03-28 15:51:04 UTC
Permalink
This frustrating experience is exactly why we added the LiteralPath
parameter!

There are 26 cmdlets that have a -Literal* parameter:

gcm | % { $cmdlet = $_; $_ | Select -expand ParameterSets | % {
if($_.Name -like "Literal*") { $cmdlet } } }

I think you are running an older version. PowerShell RTM is:

PS:5 > (gps -id $pid).Modules[0].FileVersionInfo.FileVersion
6.0.5429.0 (winmain(wmbla).060830-0116)

Lee
Post by Whisperer
After reading around about square brackets in names of files I can
understand
the need for using escape characters when referring to such files but
the comments I have found always assume the string for the file name
is
entered manually.
This is no use when the filename is retrieved programmatically e.g.
elsewhere in a script
Also various comments refer to using single quotation marks around
strings to
stop powershell interpreting wildcard characters.
I have been unable to get this working, specifically when using the
get-item or get-acl commands
(PERHAPS someone can me an example to try on my machine)
Even if I could get it working I again see potential problems when the
filename string is retrieved programmatically.
(PERHAPS again someone can me an example to try on my machine)
Another suggestion which I have read is to use the parameter
-LiteralPath
This is suggested when using get-childitem.
This parameter is not an option on my Powershell and neither is it an
option for get-item and get-acl.
AM I on the right version of Powershell? I have version 1.0.9567.0
according to Add-Remove Programs.
In frustration I have been performing tests and think I have cracked
it.
Trying to explain what I have found is not easy but I have tried my
best!
The following text takes you step-by-step through what I did and what I
found.
I think this is the clearest way I can come up with.
Create a folder with one file in called test[1].txt
$a=(get-item *).name
This sets $a to be the string test[1].txt
get-acl *
Cannot find path 'test[1].sfx' because it does not exist.
The command is interpreting the [] as wildcards - see Follow up
exercise below (at end)
get-acl $a
This produces no output as it is interpreting the [] in $a as wildcards
and hence
the command is actually looking for a file named test1.txt - see Follow
up exercise below (at end)
To get the required results the [ and ] characters in the name returned
by
get-item need escaping to stop them being interpreted as wildcards.
This can be done by using the string method .replace to insert escape
characters i.e.`
You might think the form would be .replace("[","`[") except this will
not work
In the first instance, powershell checks for wildcards in the first
parameter of the replace so
the first [ in this command is interpreted as a wildcard - which is
meaningless as there is no ] to pair with it
The form .replace("`[","`[") is correct in the first parameter i.e. it
will search for instances of [ but
the form fails because the `[ in the second parameter is interpreted as
an escaped [ so the replacement string is
simply [ i.e. this form replaces [ with [ - nothing changes
NOTE the second parameter does not interpret [ or ] as a wildcard so
using a single ` is
no different to having no ` at all
The form .replace("`[","``[") works because the double backtick `` in
the second parameter is treated as
an escaped backtick and the [ is not treated as a wildcard in the
second parameter so
the resultant replacement string is `[
So to replace all instances of [ or ] with `[ or `] the complete form
replace("`[","``[").replace("`]","``]")
get-acl ((get-item *).name.replace("`[","``[").replace("`]","``]"))
Also....
get-acl ((get-item
*).name.replace("`[","````[").replace("`]","````]"))
and the following form does work - but again I haven't got my head
get-acl ((get-item
*).name.replace("`[","``````[").replace("`]","``````]"))
There must be a better way than this....
Again any example of how to do all this using snigle quotation marks
would be
appreciated - particularly when done inside a script or over two
command line entries
e.g. a working example of the following (where again the get-acl
command produces no output)
$a='test[1].txt'
get-acl $a
Follow up exercise
Create a file called test1.txt in the test folder
i.e. the folder now contains test[1].txt and test1.txt
get-item *
Name
----
test1.txt
test[1].txt
get-acl *
Path
----
test1.txt
test1.txt
The get-acl command is interpreting the wildcards in the strings
returned from the expansion of
the * wildcard.
Further investigations (by tweeking permissions) show that get-acl is
returning 2 instances of
the exact same file object.
--
Whisperer
Loading...