2

I'm trying to run a simple icacls to a directory on my computer and I'm facing this error:


PS C:\Users\gguer\Documents> icacls.exe '.\My Digital Editions\'
.\My Digital Editions": The filename, directory name, or volume label syntax is incorrect.
Successfully processed 0 files; Failed processing 1 files

I'm using single quotes to escape the spaces as I was thought, so I don't know what is the issue here.

0

2 Answers 2

4

To add an explanation to your own effective workaround (not including a trailing \ in your argument):

What you're seeing is a bug in Windows PowerShell with respect to how it passes arguments to external programs - this problem has been fixed in PowerShell (Core) 7.

Behind the scenes, PowerShell (of necessity) translates your single-quoted argument containing spaces to a double-quoted form, because external CLIs can only be assumed to understand "..." quoting.

The command-line parsing rules used by most CLIs consider the sequence \" to be an escaped " character, i.e. a " character to be considered a verbatim part of the argument rather than delimiting it.

Therefore, a verbatim \ at the end of a double-quoted string must itself be escaped as \\ in order to be recognized as such - this is what Windows PowerShell neglects to do:

That is, Windows PowerShell translates your call as follows:

# Resulting command line as used behind the scenes for actual invocation.
# WinPS: BROKEN, because the \ at the end isn't escaped.
icacls.exe ".\My Digital Editions\"

When icacls.exe parses this command line, it sees verbatim .\My Digital Editions" (note the verbatim " at the end), as reflected in the error message.

PowerShell (Core) 7, by contrast, does perform the necessary escaping:

# Resulting command line as used behind the scenes for actual invocation.
# PowerShell (Core): OK
icacls.exe ".\My Digital Editions\\"

Workarounds:

  • In a literal path, simply omit a trailing \ - which won't work for a root path, however, and it also assumes that this doesn't change the meaning of the argument from the target program's perspective (it doesn't for icacls.exe).

    • Programmatic solution:

      $path = '.\My Digital Editions\'
      icacls.exe $path.TrimEnd('\')  # !! Doesn't work for ROOT paths, e.g. "C:\"
      
  • Alternatively - which also works for root paths - manually double the trailing \

    • Quick-and-dirty programmatic solution, knowing that file-system paths may contain duplicated \ separators without ill-effects (however, it may affect path comparisons):

      icacls.exe "$path\"
      
  • A robust, cross-edition programmatic solution that doesn't modify the argument is a bit more cumbersome:

    icacls.exe $(if ($path.EndsWith('\') -and $PSVersionTable.PSEdition -ne 'Core') { "$path\" } else { $path })
    

As an aside:

A related bug that affects how " (double quotes) embedded in arguments are passed to external programs affects PowerShell (Core) 7 up to v7.2.x - see this answer.

Sign up to request clarification or add additional context in comments.

Comments

1

Solved! Just had to remove the last backslash. Cheers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.