Windows: Копирование / перемещение файла с регулярными выражениями имени файла?


10

я в основном хочу бежать:

C:\>xcopy [0-9]{13}\.(gif|jpg|png) s:\TargetFolder /s

я знаю xcopy, не поддерживает регулярные выражения поиска файлов.

я не могу узнать , как узнать, если PowerShell имеет Cmdletдля копирования файлов; и если это так, как выяснить, поддерживает ли оно сопоставление имени файла с регулярным выражением.

Может кто-нибудь придумать, как выполнить рекурсивное копирование / перемещение файла с помощью сопоставления имен регулярных выражений?


1
это должно быть перемещено в stackoverflow правильно?
— user33788

1
@smoknheap: Это может быть и другое, и я считаю, что сценарии Powershell становятся все более и более мощным инструментом для пользователей. Это скорее вопрос замены xcopy, чем вопрос сценариев.
— Doltknuckle

Ответы:


5

Мне нравится использовать все команды Powershell, когда я могу. После небольшого тестирования это лучшее, что я могу сделать.

$source = "C:\test" 
$destination = "C:\test2" 
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"

$bin = Get-ChildItem -Path $source | Where-Object {$_.Name -match $filter} 
foreach ($item in $bin) {Copy-Item -Path $item.FullName -Destination $destination}

Первые три строки просто для облегчения чтения, вы можете определить переменные внутри фактических команд, если хотите. Ключ к этому примеру кода - команда «Где-объект», которая является фильтром, который принимает сопоставление с регулярным выражением. Следует отметить, что поддержка регулярных выражений немного странная. Я нашел ссылку PDF карту здесь , которая имеет поддерживаемые символы на левой стороне.

[РЕДАКТИРОВАТЬ]

Как уже упоминалось "@Johannes Rössel", вы также можете уменьшить последние две строки до одной строки.

((Get-ChildItem -Path $source) -match $filter) | Copy-Item -Destination $destination

Основное отличие состоит в том, что метод Йоханнеса выполняет фильтрацию объектов, а мой - фильтрацию текста. При работе с Powershell почти всегда лучше использовать объекты.

[EDIT2]

Как упоминалось в @smoknheap, приведенные выше сценарии сгладят структуру папок и поместят все ваши файлы в одну папку. Я не уверен, есть ли переключатель, который сохраняет структуру папок. Я попробовал переключатель -Recurse, и это не помогает. Единственный способ заставить это работать - вернуться к манипуляции со строками и добавить папки в мой фильтр.

$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
    Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    }

Я уверен, что есть более элегантный способ сделать это, но из моих тестов это работает. Он собирает все и затем фильтрует как совпадения имен, так и объекты папок. Мне пришлось использовать метод ToString (), чтобы получить доступ к манипуляции со строками.

[EDIT3]

Теперь, если вы хотите сообщить путь, убедитесь, что у вас все правильно. Вы можете использовать команду «Write-Host». Вот код, который даст вам несколько советов о том, что происходит.

cls
$source = "C:\test" 
$destination = "C:\test2" 
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"

$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
    Write-Host "
----
Obj: $item
Path: "$item.fullname"
Destination: "$item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    }

Это должно вернуть соответствующие строки. Если вы где-нибудь ничего не получите, вы будете знать, с какими предметами возникают проблемы.

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


Обратите внимание, что вам не нужно использовать $item.FullNameего - соответствующее свойство берется автоматически, если вы передаете объект FileInfo (имхо, вы не должны этого делать , поскольку мощь PowerShell заключается в передаче структурированных объектов, а не строк). Кроме того, вы можете поместить все в один конвейер: ((gci $source) -match $filter) | cp -dest $destination(слегка адаптированный для краткости - не стесняйтесь менять; я просто говорю, что в foreachэтом нет необходимости).
— Джои

Когда я тестировал его, я не мог правильно передать объекты. Это заставляет меня использовать команду foreach. Я попробую ваш код и посмотрю, что произойдет. Спасибо что подметил это.
— Doltknuckle

это имеет ту же проблему, что и у меня, где он сглаживает каталог назначения? xcopy обычно сохраняет структуру каталогов в целевом каталоге, верно?
— user33788

Copy-Item : Cannot bind argument to parameter 'Path' because it is null
— Ян Бойд

Обратите внимание, что Trimон не предназначен для удаления строки из конца другой строки, вместо этого он удаляет все вхождения символов в строке параметра из начала и конца строки, для которой она вызывается. В вашем случае, если он $item.Nameсодержит заглавную букву C, он также удалит букву диска C из начала строки.
— Андрис

3

PowerShell - отличный инструмент для решения этой задачи. Вы можете использовать командлет Copy-Item для процесса копирования. Вы можете передать его с помощью других командлетов для сложных команд копирования, вот кто-то, кто сделал именно это :)

Регулярные выражения используют класс .NET RegEx из пространства имен System.Text.RegularExpressions, в этом классе есть быстрые инструкции

В PowerShell также есть операторы -match и -replace, которые можно использовать при конвейерной передаче с copy-item

Есть также инструменты, которые помогут вам создать сам RegEx, например, приятель RegEx


Имхо, -matchи -replaceследует упомянуть, прежде чем идти в System.Text.RegularExpressions.RegEx. По крайней мере, я редко пользуюсь [regex]напрямую; Однако я действительно часто использую -matchи -replaceоператор. Что касается создания регулярных выражений, я обнаружил, что PowerShell весьма полезен для тестирования и уточнения регулярного выражения, которое вы пишете.
— Джои

я попросил ответить на ваш ответ на этот вопрос: superuser.com/questions/149808/…
— Иан Бойд

0

как идея, но нуждается в некоторой работе

dir -r | ? {$ _ -match '[0-9] {13} \. (gif | jpg | png)'} | % {xcopy $ _. полное имя c: \ temp}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.