Windows: Копіювання / переміщення файлу з регулярними виразами назви файлів?


10

я в основному хочу запустити:

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

я знаю xcopy, не підтримує пошук файлів регулярного виразу.

я не можу дізнатися, як дізнатися, чи має PowerShellCmdlet копіювати файли; і якщо це так, як дізнатися, чи підтримує він регулярне узгодження імені файлу виразів.

Чи може хтось придумати спосіб виконати рекурсивну копію / переміщення файлу із збігом імені файлу regex?


1
це слід перенести на stackoverflow правильно?
користувач33788

1
@smoknheap: Можливо, і те, і інше, я вважаю, що сценарії Powershell стають все більш інструментом користувача Power. Це скоріше питання про заміну 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 карту тут , яка має підтримувані символи на лівій стороні.

[EDIT]

Як згадував "@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]

Тепер, якщо ви хочете повідомити про шлях, щоб переконатися, що у вас все правильно. Можна скористатися командою "Написати-хост". Ось код, який дасть вам підказки щодо того, що відбувається.

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немає зайвого).
Joey

Коли я тестував її, я не міг заставити об'єкти правильно труби. Тобто черга змушує мене використовувати команду foreach. Я спробую ваш код, і я побачу, що станеться. Дякуємо, що вказали на це.
Doltknuckle

це проблема має таку, що і моя, де вона випрямлює каталог призначення? xcopy зазвичай зберігає структуру каталогу в каталозі призначення, правда?
користувач33788

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

Існують також інструменти, які допоможуть вам створити сам RegEx, наприклад, RegEx приятель


Імхо, -matchі його -replaceслід згадати перед тим, як заходити System.Text.RegularExpressions.RegEx. Принаймні для мене я рідко використовую [regex]безпосередньо; Однак я дійсно часто використовую -matchі -replaceоператор. Щодо створення регулярних виразів, я виявив, що PowerShell є дуже корисним для тестування та уточнення регулярного виразу, про який ви пишете.
Joey

я попросив відповіді на вашу відповідь у цьому запитанні: superuser.com/questions/149808/…
Ian Boyd

0

як ідея, але потребує певної роботи

dir -r | ? {$ _ -match '[0-9] {13} \. (gif | jpg | png)'} | % {xcopy $ _. fullname c: \ temp}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.