组织文件夹的脚本

Script to organize folders

我需要整理很多文件夹,这些文件夹的名称必须有某种格式。我需要重命名它们并像这样放置它们:

parent folder 2nd name + "_" + 2 digits + "_" + folder name

这需要在执行 .ps1 的每个文件夹中发生。

这里有一些更好的解释,这里有一些文件夹:

00_00_Master folder
+- 00_01_Activities
`- 00_02_Schedules
   +- 02_00_dir1
   `- 02_01_dir2

如您所见,00_02_Schedules 中的子文件夹以第 第二个 "name".

开头

等等,包括所有文件夹(不是文件)。现在为了更好的解释,我在 00_02_Schedules 中添加了(这会经常发生)3 个文件夹。应该是这样的(执行前后.ps1)


之前:

...
`- 00_02 Schedules
   +- 02_00_dir1
   +- 02_01_dir2
   +- dir3
   +- 12345dir4
   `- 01_01_dir5

之后:

...
`- 00_02 Schedules
   +- 02_00_dir1
   +- 02_01_dir2
   +- 02_02_dir3
   +- 02_03_dir4
   `- 02_04_dir5

我会试着解释一下(我把我所有的代码都放上去了,即使我认为有些现在没用了)

$var1 = 0
$var2 = 0
# It always has to work in the same place, never with a fixed path like
# C:\Users\etc\etc
$arr1 = Get-ChildItem -Path .\ -Directory 
$arr2 = New-Object System.Collections.ArrayList
[string]$dir = Get-Location

$ruta = $dir | Split-Path -Leaf

# Did these 2 things because I needed the folder's name, I didn't know how 
# to do it better

# I think we can say this following code is useless now, I think I tried to do
# an array of arrays so I could cleave the name 

foreach ($Name in $arr1) {
    [void]$arr2.Add($Name)
}

foreach ($Directory in $arr1) {
    if ($Directory -match '^[0-9].*') {
        Rename-Item $Directory -NewName { [string]($_.Name).Substring(5) } 

        # This is the part I've being having most problems with. I may say the
        # code works...as long a folder's name doesn't start with a number,
        # because it enters inside the loop and many error logs pops out. Also
        # it renames the folders previously renamed like 00_01_00_01, when it's
        # supposed to delete before rename them.

        # Also, I think it won't work if the numeric extension isn't equal to 5.
    }
}

$arr3 = $ruta -split '_'
$foldername = $arr3[1]
# Works, It splits and give me the second "piece" between the 2 "_"

foreach ($Directory in $arr1) {
    Rename-Item "$Directory" -NewName $("$foldername" + "_" + "$var1" + "$var2" + "_" + $Directory.Name)

    # I think it should have been: (I put it that way before) 
    # $("$foldername" + "_" + "$var2" + "$var1" + "_" + $Directory.Name)
    # but if I did that way, it renamed them like 10,20,30 instead of 01,02,03 etc.

    $var++

    if ($var1 = 9) {
        $var1 = 0
        $var2++
        # I suppose is not fancy, but in the result output I can see 2 numbers, not 1
    }
}

还有一件事,是否可以将此(固定)代码以递归方式转换为在所有文件夹中工作? (会节省很多工作和执行)。

Get-ChildItem -Directory -Recurse | ForEach { #Get All Directories
    $a = 0 #Reset Indexing to 01
    Get-ChildItem $_.FullName -File | ForEach {
        $ParentFolderSecond = ($_.Directory.Parent.Name -split '_')[1] #Second part of folder's parent
        $Number = $a++ #Number incrementing by 1
        $FolderName = $_.Directory.Name #folder's name
        "$($ParentFolderSecond)_$($Number.ToString("00"))_$($FolderName)$($_.Extension)" #put this into a rename-item if it works OK.
    }
}

这符合您的规格吗?

它应该按原样递归工作,但我想我在父文件夹部分遗漏了一些东西。

它不会重命名任何东西,只是吐出一个文件名列表 'will'。

我可能会这样做:

Get-ChildItem -Recurse -Directory | Where-Object {
    # find schedule directories below the current working directory
    $_.Name -match '^\d{2}_(\d{2})_Schedules$'
} | ForEach-Object {
    $prefix  = $matches[1]
    $pattern = "^${prefix}_(\d{2})_"

    # enumerate subfolders of schedule directory
    $folders = Get-ChildItem $_.DirectoryName -Directory

    # find highest existing index of folders that already conform to the
    # name schema
    $lastindex = $folders |
                 Where-Object { $_.Name -match $pattern } |
                 ForEach-Object { [int]$matches[1] } |
                 Sort-Object |
                 Select-Object -Last 1
    $nextindex = if ($lastindex) { $lastindex + 1 } else { 0 }

    # rename folders that don't conform to the name schema starting with the
    # index after the highest existing index (or 0 if there was none), remove
    # digits and underscores from beginning of folder name
    $folders | Where-Object {
        $_.Name -notmatch $pattern
    } | Rename-Item -NewName {
        $_.Name -replace '^\d(?:[_\d]*)', "${prefix}_${script:nextindex}_"
        ${script:nextindex}++
    }
}

在这种初始情况下:

> tree
└───00_00_Master folder
    ├──00_01_Activities
    └──00_02_Schedules
       ├──01_01_dir5
       ├──02_00_dir1
       ├──02_01_dir2
       ├──12345dir4
       └──dir3

此脚本(调整 Set-Location 以适合您的环境):

## Q:\Test17\SO_45750567.ps1
Function Test-DirSchema ($DirName) {
    # assume parent is already processed and complies with schema
    $ThisDir = GI $DirName
    # Get parent's second number for our first
    $First = $ThisDir.Parent.Name.Split('_')[1]
    If ($ThisDir.Name -Match "^$($First)_\d{2}_.*") {
        "{0} : {1} complies with schema" -f $First,$ThisDir.Name
    } else {
        $Highest = (gci "$($ThisDir.Parent)$($First)_??_*"|Sort|Select -Last 1).Name
        $Second = [int]($Highest -Replace('^\d{2}_(\d{2})_.*',''))
        $Second = ($Second + 1).ToString('00')
        "{0} : {1} does not comply with schema" -F $First,$ThisDir.Name
        $NewName = "{0}_{1}_{2}" -F $First, $Second,$ThisDir.Name.TrimStart('0123456789_')
        "new: {0}" -F $NewName
        $ThisDir | Rename-Item -NewName $NewName
    }
    "----"
}
Set-Location "A:[=11=]_00_Master folder"

Get-ChildItem "[0-9][0-9]_*" -Rec |
    Where-Object {$_.PSIsContainer} |
        ForEach-Object {Test-DirSchema $_.FullName}

使用此输出:

>  Q:\Test17\SO_45750567.ps1
02 : 01_01_dir5 does not comply with schema
new: 02_02_dir5
----
02 : 02_00_dir1 complies with schema
----
02 : 02_01_dir2 complies with schema
----
02 : 12345dir4 does not comply with schema
new: 02_03_dir4
----
02 : dir3 does not comply with schema
new: 02_04_dir3
----

会有这样的结局:

> tree
└───00_00_Master folder
    ├──00_01_Activities
    └──00_02_Schedules
       ├──02_00_dir1
       ├──02_01_dir2
       ├──02_02_dir5
       ├──02_03_dir4
       └──02_04_dir3

由于排序不同,订单不完全是您的。 如果没有之前的号码,它将以 01.

开头