All my files are in specific folders:
17\1\1\PRO
17\1\2\PRO
17\2\1\PRO
xx\xx\xx\PRO
- 17 is the year (so 18 for next year etc)
- the first 1 is the folder specifying the case number (can be up to 100).
- The second 1 is the sub parts on the case number.
That last 1 has a folder PRO
in it where all data resides.
We need to move these files, but the files need to stay inside their respective "PRO" folders.
For example:
- a file in
17\1\1\pro\xxx\www\
needs to go to17\1\1\pro\movies
- a file in
17\2\2\pro\xxdfsdf\eeee\
needs to go to17\2\2\pro\movies
.
The movies folder should get created if there are files to move.
I need to get a part of the full name of a file and move the file there to the "movie" folder. The problem is I do not know how to split the full name, add \movies to it and move the files there.
This is my code so far:
Get-ChildItem -Path $mypath -Recurse -File -Filter $extension | select $_Fullname |
Move-Item -Force -Destination ($_Fullname.Split("pro"))
If you don't know how many directories there are, I would do something like this:
Get-ChildItem -Path $mypath -Recurse -File -Filter $extension | ForEach-Object {
if ($_.FullName.IndexOf('\PRO\') -gt 0) {
$Destination = Join-Path -Path $_.FullName.Substring(0,$_.FullName.IndexOf('\PRO\') + 5) -ChildPath 'movies';
New-Item $Destination -ItemType Directory -ea Ignore;
$_ | Move-Item -Destination $Destination;
} else {
throw ("\PRO\ path not found in '$($_.FullName)'");
}
}
This will work fine as long as your paths only have \pro\
once. If they have it more than once like customer\pro\17\pro\17\1\1\pro\xx\yy\zz\www
and you need the last index, then use $_.FullName.LastIndexOf('\pro\')
.
If you've got \pro\
directories both before and after the directory that .\pro\movies\
is in, well, you're in trouble. You'll probably have to find a different point of reference.
If the destination is always "movies subdirectory of the grandparent directory of the file's directory" you can build the destination path relative to the file's location:
Get-ChildItem ... | ForEach-Object {
$dst = Join-Path $_.Directory '..\..\movies'
if (-not (Test-Path -LiteralPath $dst -PathType Container)) {
New-Item -Type Directory -Path $dst | Out-Null
}
Move-Item $_.FullName -Destination $dst
}
If the PRO
directory is your anchor you could use a regular expression replacement like this instead:
Get-ChildItem ... | ForEach-Object {
$dst = $_.Directory -replace '^(.*\\\d+\\\d+\\\d+\\PRO)\\.*', '$1\movies'
if (-not (Test-Path -LiteralPath $dst -PathType Container)) {
New-Item -Type Directory -Path $dst | Out-Null
}
Move-Item $_.FullName -Destination $dst
}
With a set of folders
17\1\1\PRO
17\1\2\PRO
17\2\1\PRO
You could try the following
$RootPaths = Get-ChildItem -Path C:\folder\*\*\*\pro
$RootPaths
will then contain all 3 paths mentioned above and the code below will move all files to the appropriate directory.
ForEach( $Path in $RootPaths)
{
$Movies = Join-Path $Path -Child "Movies"
If( -not (Test-Path $Movies ) ) { New-Item -Path $Movies -ItemType Directory }
Get-ChildItem -Path $Path -Recurse -File -Filter $Extension |
Move-Item -Path $_.FullName -Destination "$( $Path )\Movies"
}
This way it doesn't matter how many levels down your files are. They always get moved to the same directory.
来源:https://stackoverflow.com/questions/45591348/move-files-with-specific-extension-to-folder-in-higher-hierarchy