Переместить каталоги, которые соответствуют заданному регулярному выражению - PullRequest
2 голосов
/ 22 января 2020

Я пытаюсь переместить каталоги с их содержимым. Имена каталогов - это буквы, за которыми следуют цифры: a2, a2321, sdadsa2321321, поэтому регулярное выражение будет [a-zA-Z]+\d+. Однако это не работает.

$SourceDirectoryPath = "C:/directory/[a-zA-Z]+\d+"
$TargetFilePath = "C:/directory/target"

New-Item -ItemType "directory" -Path $TargetFilePath
Move-Item -Path $SourceDirectoryPath -Destination $TargetFilePath -Force

Если я заменим [a-zA-Z]+\d+ простыми подстановочными знаками, такими как a*, он перемещается, перемещает несколько каталогов, это доказывает, что [a-zA-Z]+\d+ является единственной неверной частью скрипта.

Вопрос: Какая правильная форма регулярного выражения [a-zA-Z]+\d+ в Powershell? Это регулярное выражение полностью верно в Java, но по какой-то причине оно здесь не работает.

Ответы [ 3 ]

1 голос
/ 22 января 2020

Может быть, это то, что вы хотите:

$sourceDir = 'D:\source'
$destDir   = 'D:\destination'

$pattern = '^.*[a-zA-Z]+\d+$'
$baseDir = Get-ChildItem -Path $sourceDir -Recurse -Directory

foreach( $directory in $baseDir ) {

    if( $directory.Name -match $pattern ) {
        Move-Item -Path $directory.FullName -Destination $destDir -Force
    }
}
0 голосов
/ 22 января 2020

Если я заменим [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 сама может интерполировать, заранее , в частности $ и `.

0 голосов
/ 22 января 2020

Чтобы использовать регулярное выражение для файлов и папок с Get-ChildItem, вам необходимо использовать предложение Where-Object.

Это должно сделать это:

$SourceDirectoryPath = 'C:\directory'
$TargetFilePath      = 'C:\directory\target'

# create the target path if it does not exist yet
if (!(Test-Path -Path $TargetFilePath -PathType Container)) {
    $null = New-Item -Path $TargetFilePath -ItemType Directory
}

Get-ChildItem -Path $SourceDirectoryPath -Directory | 
    Where-Object { $_.Name -match '^[a-z]+\d+$' } | 
    ForEach-Object { $_ | Move-Item -Destination $TargetFilePath -Force }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...