Запуск команды Powershell с переменным параметром -Path

Может кто-нибудь объяснить мне следующее поведение?

PS C:\Users\Kenny> $filePath = "C:\\Complicated.File.Path.That.Has.Special-Chars`[but-no.spaces`]and.definitely.exists\"
PS C:\Users\Kenny> cd $filePath
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd $filePath
+ ~~~~~~~~~~~~~~~~                                 
    + CategoryInfo          : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

PS C:\Users\Kenny> cd 'C:\\Complicated.File.Path.That.Has.Special-Chars`[but-no.spaces`]and.definitely.exists\'
PS C:\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists> cd c:
PS C:\Users\Kenny> Write-Host $filePath
C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\
PS C:\Users\Kenny> cd "$filePath"
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd "$filePath"
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

PS C:\Users\Kenny> cd ${filePath}
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd ${originalPath}
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

PS C:\Users\Kenny> cd ${$filePath}
cd : Cannot process argument because the value of argument "path" is null. Change the value of argument "path" to a
non-null value.
At line:1 char:1
+ cd ${$filePath}
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-Location], PSArgumentNullException
    + FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand

PS C:\Users\Kenny> cd $($filePath)
cd : Cannot find path 'C:\\Complicated.File.Path.That.Has.Special-Chars[but-no.spaces]and.definitely.exists\' because it does not exist.
At line:1 char:1
+ cd $($filePath)
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\\Complicated...initely.exists\:String) [Set-Location], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

Если бы у меня была копейка за каждую минуту, потраченную на то, что PowerShell настаивает на том, что обратные кавычки, кавычки и другие метасимволы в самый раз, я был бы самым богатым человеком на Земле! Кто-нибудь, пожалуйста, спасите меня от этого безумия!

И, кстати, я на самом деле пытаюсь пройтись по куче папок и удалить все, что не является видеофайлом, вот так...

Remove-Item -Path $filePath -Recurse -Exclude '*.avi','*.mkv','*.mp4'

... который не работает (предположительно) по той же причине: невозможность передать переменную параметру -Path. И если кто-то чувствует себя действительно щедрым, он также может помочь мне с это. МТИА! :D


person Kenny83    schedule 01.11.2019    source источник
comment
FWIW: Procmon сообщает, что Powershell ищет C:\Complicated.File.Path.That.Has.Special-Chars?and.definitely.exists. Вся часть в квадратных скобках преобразуется в один подстановочный знак ?.   -  person vonPryz    schedule 01.11.2019
comment
Почему вы используете путь компакт-диска, когда все, что вы делаете, это ищете файлы для удаления?   -  person Scepticalist    schedule 01.11.2019
comment
@Scepticalist Я начал с команды Remove-Item..., опубликованной выше, затем, после того, как я пробил головой о кирпичную стену в течение 1/2 часа, попытался максимально упростить команду, так как я знал, что она должна иметь какое-то отношение к специальным символы интерпретируются, хотя я использовал обратные кавычки, чтобы избежать их, но хотел проверить это.   -  person Kenny83    schedule 01.11.2019


Ответы (3)


Используйте -LiteralPath вместо -Path, потому что некоторые специальные символы интерпретируются как -Path.

Remove-Item -LiteralPath
person Patrick    schedule 01.11.2019
comment
Ты человек! Я думал, что какое-то время принимал сумасшедшие таблетки! +25 вам, сэр :D А также большое спасибо и +1 @vonPryz, который тоже это поймал. С какой стати обратные кавычки перед квадратными скобками не помешали мне потратить на это час?? - person Kenny83; 01.11.2019
comment
не за что (я тоже боролся несколько часов, когда это впервые появилось у меня...). Понятия не имею о обратных кавычках. - person Patrick; 01.11.2019
comment
Хм, ладно... все равно спасибо. Ирония этой ситуации в том, что использование -LiteralPath теперь не позволяет мне выполнять поиск по подстановочным знакам, то есть Remove-Item -LiteralPath C:\my.file.[path]\* -Recurse -Exclude '*.avi','*.mkv','*.mp4' не работает, так как * интерпретируется буквально, лол. Итак, теперь я изучаю использование Get-ChildItem -LiteralPath C:\my.file.[path] | Where-Object ... | Remove-Item. Надеюсь, это наконец даст мне решение! - person Kenny83; 01.11.2019

Специальные символы — это так весело в PS, верно?

-LiteralPath работает точно так же, как объяснил Патрик, но они не позволяют использовать подстановочные знаки; потому что они буквальны.

Пробовали ли вы использовать одинарные кавычки ' вместо двойных кавычек ". Это позволяет вам экранировать специальные символы, при этом оценивая подстановочные знаки. Попробуйте выполнить следующие команды:

New-Item -Path 'C:\Users\username\PSScripts\bracket`[\te$t.txt'
Get-Item -Path  'C:\Users\username\PSScripts\bracket`[\*'

Кроме того, если это поможет, я использую VSCode для большинства сценариев, и, если вы используете завершение с помощью табуляции, он отформатирует это правильно для вас.

Надеюсь, это поможет!

person TheIdesOfMark    schedule 01.11.2019
comment
В конце концов я нашел другое решение проблемы, но теперь пожалел об этом, чтобы проверить вашу теорию. TYVM в любом случае за попытку помочь! Проголосуйте за ваши проблемы: D И я бы дал вам еще два, если бы мог, потому что специальные символы - это забавный комментарий, LOL! Примерно так же весело, как втирать соль в открытую рану, верно?? :P Также спасибо за совет VSCode; обязательно воспользуюсь теперь! - person Kenny83; 01.11.2019

Решением моей общей проблемы стала эта строка моего пакетного сценария:

powershell -Command "Get-ChildItem -Recurse -LiteralPath %filePath% | Where-Object Extension -match '^(?!(\.avi|\.mkv|\.mp4)$)' | Remove-Item"

Сложнее всего было разобраться с регулярным выражением, так как я раньше не использовал отрицательный просмотр вперед, но после ~2 часов общего времени, потраченного на эту одну строку кода, оно наконец-то заработало!

person Kenny83    schedule 01.11.2019