Windows: Dosya adı / dosya adı normal ifadeleriyle kopyalama / taşıma?


10

temelde çalıştırmak istiyorum :

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

xcopynormal ifade dosya adı aramalarını desteklemediğini biliyorum .

i PowerShellCmdlet dosyaları kopyalamak için bir olup olmadığını öğrenmek nasıl bulamıyorum ; ve eğer varsa, normal ifade dosya adı eşleşmesini destekleyip desteklemediğini bulma.

Herkes regex dosya adı eşleme ile özyinelemeli dosya kopyalama / taşıma gerçekleştirmek için bir yol düşünebilir miyim?


1
bu yığın akışına taşınmalı değil mi?
user33788

1
@ smoknheap: Her ikisi de olabilir, Powershell betiklemesinin giderek daha fazla bir Power User aracı haline geldiğini fark ettim. Bu, bir kodlama sorusundan çok bir xcopy değiştirme sorusudur.
Doltknuckle

Yanıtlar:


5

Yapabildiğim zaman tüm Powershell komutlarını kullanmayı seviyorum. Biraz test yaptıktan sonra yapabileceğim en iyisi bu.

$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}

İlk üç satır bunu okumayı kolaylaştırmak için, isterseniz gerçek komutların içindeki değişkenleri tanımlayabilirsiniz. Bu kod örneğinin anahtarı, normal ifade eşleşmesini kabul eden bir filtre olan "Where-Object" komutudur. Normal ifade desteğinin biraz garip olduğu belirtilmelidir. Bir PDF referans kart buldum burada sol tarafta desteklenen karakter var.

[DÜZENLE]

"@Johannes Rössel" de belirtildiği gibi, son iki satırı tek bir satıra da azaltabilirsiniz.

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

Temel fark, Johannes'in yolunun nesne filtrelemesi ve benim yolumun metin filtrelemesidir. Powershell ile çalışırken, nesneleri kullanmak neredeyse her zaman daha iyidir.

[EDIT2]

@Smoknheap'ın belirttiği gibi, yukarıdaki komut dosyaları klasör yapısını düzleştirir ve tüm dosyalarınızı tek bir klasöre koyar. Klasör yapısını koruyan bir anahtar olup olmadığından emin değilim. -Recurse anahtarını denedim ve işe yaramadı. Bunu işe almak için tek yolu dize manipülasyona geri dönmek ve benim filtre klasör eklemek için.

$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,"")
    }

Bunu yapmanın daha zarif bir yolu olduğundan eminim, ancak testlerimden işe yarıyor. Her şeyi toplar ve daha sonra hem ad eşleşmeleri hem de klasör nesneleri için filtreler. Dize manipülasyonuna erişmek için ToString () yöntemini kullanmak zorunda kaldı.

[EDIT3]

Şimdi her şeyi doğru yaptığınızdan emin olmak için yolu bildirmek istiyorsanız. "Write-Host" Komutunu kullanabilirsiniz. İşte size neler olduğuna dair bazı ipuçları verecek olan kod.

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,"")
    }

Bu, ilgili dizeleri döndürmelidir. Bir yerde hiçbir şey almazsanız, hangi öğenin sorun yaşadığını bilirsiniz.

Bu yardımcı olur umarım


$item.FullNameOrada kullanmanız gerekmediğine dikkat edin - bir FileInfo nesnesini iletirseniz uygun özellik otomatik olarak alınır (imho, yapmamalısınız, çünkü PowerShell'in gücü dizeden değil yapılandırılmış nesnelerden geçmektedir). Dahası, her şeyi tek bir boru hattına koyabilirsiniz: ((gci $source) -match $filter) | cp -dest $destination(kısalık için biraz uyarlanmış - değişmekten çekinmeyin; sadece foreachorada gereksiz olduğunu söylüyorum ).
Joey

Test ederken, nesneleri doğru şekilde boruya bağlayamadım. Bu beni foreach komutunu kullanmaya zorlar. Kodunuzu bir deneyeceğim ve ne olacağını göreceğim. Bunu işaret ettiğiniz için teşekkürler.
Doltknuckle

hedef dizini düzleştirdiği benimkiyle aynı soruna sahip mi? xcopy normalde hedef dizindeki dizin yapısını korur, değil mi?
user33788

Copy-Item : Cannot bind argument to parameter 'Path' because it is null
Ian Boyd

TrimBir dizenin başka bir dizenin sonundan kaldırılması amaçlanmadığını, bunun yerine parametre dizesindeki karakterlerin tüm örneklerini çağrıldığı dizenin başından ve sonundan kaldırdığını lütfen unutmayın . Büyük harf $item.NameC içeriyorsa, C harfinin başlangıcından da kaldırır.
Andris

3

PowerShell bu görev için mükemmel bir araçtır. Kopyalama işlemi için Copy-Item cmdlet'ini kullanabilirsiniz . Karmaşık kopya komutları için diğer cmdlet'lerle boru hattı oluşturabilirsiniz, işte tam olarak bunu yapan biri :)

Düzenli ifadeler System.Text.RegularExpressions ad alanından .NET RegEx sınıfını kullanır , bu sınıfta hızlı nasıl yapılır

PowerShell ayrıca, kopya öğeyle boru hattı oluştururken kullanılabilecek -match ve -replace işleçlerine sahiptir

RegEx'in kendisini oluşturmanıza yardımcı olacak araçlar da vardır, örneğin RegEx arkadaşı


Imho, -matchve -replacegirmeden önce de belirtilmelidir System.Text.RegularExpressions.RegEx. En azından benim için nadiren [regex]doğrudan kullanıyorum; ancak do kullanmak sık -matchve -replaceoperatörler. Düzenli ifadeler oluştururken, PowerShell'in yazdığınız bir normal ifadeyi test etmede ve iyileştirmede oldukça yararlı olduğunu gördüm.
Joey

Bu sorudaki cevabınızın yanıtını sordum: superuser.com/questions/149808/…
Ian Boyd

0

bir fikir olarak ama biraz çalışmaya ihtiyaç var

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.