Windows: Kopieren / Verschieben von Dateien mit regulären Ausdrücken mit Dateinamen?

19003
Ian Boyd

Ich möchte grundsätzlich laufen:

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

Ich weiß, dass xcopydie Suche nach Dateinamen für reguläre Ausdrücke nicht unterstützt wird.

ich kann nicht herausfinden, wie um herauszufinden, ob Powershell eine hat, CmdletDateien zu kopieren; und wenn ja, wie Sie herausfinden, ob Dateinamen für reguläre Ausdrücke unterstützt werden.

Kann sich jemand eine Möglichkeit vorstellen, eine rekursive Datei mit Regex-Dateinamen zu kopieren / verschieben?

10
sollte dies zu stackoverflow richtig verschoben werden? user33788 vor 14 Jahren 1
@smoknheap: Es könnte beides sein, ich finde, dass Powershell-Scripting immer mehr zu einem Power User-Tool wird. Dies ist eher eine Xcopy-Ersetzungsfrage als eine Skriptfrage. Doltknuckle vor 14 Jahren 1

3 Antworten auf die Frage

4
Doltknuckle

I like using all Powershell commands when I can. After a bit of testing, this is the best I can do.

$source = "C:\test" $destination = "C:\test2" $filter = [regex] "^[0-9]\.(jpg|gif)" $bin = Get-ChildItem -Path $source | Where-Object {$_.Name -match $filter} foreach ($item in $bin) 

The first three lines are just to make this easier to read, you can define the variables inside the actual commands if you want. The key to this code sample is the the "Where-Object" command which is a filter that accepts regular expression matching. It should be noted that regular expression support is a little weird. I found a PDF reference card here that has the supported characters on the left side.

[EDIT]

As "@Johannes Rössel" mentioned, you can also reduce the last two lines down to a single line.

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

The main difference is that Johannes's way does object filtering and my way does text filtering. When working with Powershell, it's almost always better to use objects.

[EDIT2]

As @smoknheap mentioned, the above scripts will flatten out the folder structure and put all your files in one folder. I'm not sure if there is a switch that retains folder structure. I tried the -Recurse switch and it doesn't help. The only way I got this to work is to go back to string manipulation and add in folders to my filter.

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

I'm sure that there is a more elegant way to do this, but from my tests it works. It gather s everything and then filters for both name matches and folder objects. I had to use the ToString() method to gain access to the string manipulation.

[EDIT3]

Now if you want to report the pathing to make sure you have everything correct. You can use the "Write-Host" Command. Here's the code that will give you some hints as to what's going on.

cls $source = "C:\test" $destination = "C:\test2" $filter = [regex] "^[0-9]\.(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,"") } 

This should return the relevant strings. If you get nothing somewhere, you'll know what item is having problems with.

Hope this helps

Beachten Sie, dass Sie dort nicht `$ item.FullName` verwenden müssen - die entsprechende Eigenschaft wird automatisch übernommen, wenn Sie ein FileInfo-Objekt übergeben (imho sollten Sie dies nicht tun, da PowerShell die Kraft hat, strukturierte Objekte zu übergeben, nicht Zeichenfolge). Darüber hinaus können Sie alles in eine einzige Pipeline einfügen: `(((gci $ source) -match $ filter) | cp -dest $ destination` (leicht angepasst an die Kürze - ändern Sie sich gerne; ich sage nur, dass "foreach" dort nicht erforderlich ist). Joey vor 14 Jahren 0
Als ich es testete, konnte ich die Objekte nicht richtig pfeifen. Das ist wiederum zwingt mich, den foreach-Befehl zu verwenden. Ich werde Ihren Code ausprobieren und sehen, was passiert. Danke, dass du darauf hingewiesen hast. Doltknuckle vor 14 Jahren 0
Hat dies das gleiche Problem wie bei mir, wo das Zielverzeichnis abgeflacht wird? xcopy würde normalerweise die Verzeichnisstruktur im Zielverzeichnis beibehalten, oder? user33788 vor 14 Jahren 0
`Copy-Item: Das Argument kann nicht an den Parameter 'Path' gebunden werden, da es null ist Ian Boyd vor 14 Jahren 0
Bitte beachten Sie, dass `Trim 'nicht dazu gedacht ist, eine Zeichenfolge vom Ende einer anderen Zeichenfolge zu entfernen. Stattdessen werden alle Instanzen der Zeichen in der Parameterzeichenfolge vom Anfang und Ende der Zeichenfolge entfernt, für die sie aufgerufen werden. Wenn in Ihrem Fall $ item.Name ein Großbuchstabe C enthält, wird auch der Laufwerkbuchstabe C vom Anfang der Zeichenfolge entfernt. Andris vor 12 Jahren 0
@ Andris, guter Punkt. Sie müssen den Dateinamen aus dem Ziel entfernen, damit Copy-Item ordnungsgemäß funktioniert. Sie können einen anderen Ersetzungsbefehl verwenden, um den Dateinamen abzurufen. Das sollte etwas besser funktionieren. Doltknuckle vor 12 Jahren 0
2
armannvg

PowerShell is an excellent tool for that task. You can use Copy-Item cmdlet for the copying process. You can pipeline it with other cmdlets for complex copy commands, here is someone that did exactly that :)

Regular expressions use the .NET RegEx class from the System.Text.RegularExpressions namespace, there are quick how-to on these class

PowerShell also have the -match and -replace operators that can be used when pipelining with copy-item

There are also tools to help you create the RegEx itself, e.g. RegEx buddy

Imho, "-match" und "-replace" sollten erwähnt werden, bevor in "System.Text.RegularExpressions.RegEx" gewechselt wird. Zumindest für mich verwende ich selten [Regex] `direkt; Ich verwende jedoch häufig die Operatoren `-match` und` -replace '. Bei der Erstellung der regulären Ausdrücke fand ich, dass PowerShell auch beim Testen und Verfeinern einer Regex, die Sie schreiben, sehr nützlich ist. Joey vor 14 Jahren 0
Ich habe nach der Antwort auf Ihre Antwort in dieser Frage gefragt: http://superuser.com/questions/149808/powershell-file-copy-move-with-filename-regular-expressions Ian Boyd vor 14 Jahren 0
0
user33788

as an idea but needs some work

dir -r | ?{$_ -match '[0-9]\.(gif|jpg|png)'} | %