Если я заменим [a-zA-Z]+\d+
простыми подстановочными знаками, такими как a*
, он перемещается, перемещает несколько каталогов, это доказывает, что [a-zA-Z]+\d+
является единственной неверной частью скрипта.
Действительно : Параметр -Path
командлетов, связанных с файлами, может только принимать подстановочные выражения (см. about_Wildcards
), но не регулярные выражения (регулярные выражения) (см. about_Regular_Expressions
).
Несмотря на отдаленную связь, два типа выражений синтаксически различаются: подстановочные выражения концептуально и синтаксически проще, но гораздо менее мощно - и недостаточно мощно для вашего случая использования. См. AdminOfThings 'комментарий к вопросу для быстрого вступления.
Также обратите внимание, что многие командлеты PowerShell также удобно принимают подстановочные знаки в других типах аргументов (не связанных с файловой системой), таких как Get-Command *job*
, позволяющих найти все доступные команды, чье имя содержит слово job
.
В отличие от использование регулярных выражений всегда требует отдельной отдельной явной операции (если только команда явно не предназначена для принятия регулярных выражений в качестве аргументов) через операторы, такие как -match
и -replace
, командлеты, такие как Select-String
, или оператор switch
с опцией -Regex
.
В вашем случае вам необходимо отфильтровать интересующие каталоги из всех подкаталогов, комбинируя командлет Where-Object
с -match
, оператором сопоставления регулярных выражений ; синтаксически простейшая форма - использовать оператор операции (более чистая альтернатива передаче блока сценария { ... }
, в котором $_
должен использоваться для ссылки на объект ввода под рукой), как показано в следующая команда:
# Define the *parent* path of the dirs. to move.
# The actual dirs. must be filtered by regex below.
$SourceDirectoryParentPath = 'C:/directory'
$TargetFilePath = 'C:/directory/target'
# Note: If you add -Force, no error occurs if the directory already exists.
# New-Item produces output, a System.IO.DirectoryInfo in this case.
# To suppress the output, use: $null = New-Item ...
New-Item -ItemType "directory" -Path $TargetFilePath
# Enumerate the child directories of the parent path,
# and filter by whether each child directory's name matches the regex.
Get-ChildItem -Directory $SourceDirectoryParentPath |
Where-Object Name -match '^[a-z]+\d+$' |
Move-Item -Destination $TargetFilePath -Force
Обратите внимание, что я изменил регулярное выражение [a-zA-Z]+\d+
на ^[a-z]+\d+$
, потому что:
Соответствие регулярному выражению PowerShell имеет значение case- по умолчанию нечувствителен, поэтому [a-z]
охватывает как прописные, так и строчные буквы (Engli sh).
Оператор -match
выполняет подстрока сопоставление, поэтому вам нужно привязать регулярное выражение с ^
(совпадение в начале) и $
сопоставить в конце, чтобы убедиться, что входная строка вся соответствует вашей выражение.
Также обратите внимание, что я использовал одиночную строку в кавычках ('...'
) вместо строки в двойных кавычках ("..."
), что предпочтительнее для литералов регулярных выражений, так что не возникает путаницы между тем, что символы видят регулярные выражения en и какие символы PowerShell сама может интерполировать, заранее , в частности $
и `
.