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.