Мені подобається використовувати всі команди 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,"")
}
Це має повернути відповідні рядки. Якщо ви десь нічого не отримаєте, ви будете знати, з яким предметом виникають проблеми.
Сподіваюсь, це допомагає