用于组织文件夹的脚本

时间:2017-08-18 07:09:51

标签: powershell powershell-v2.0 rename

我需要组织许多文件夹,这些文件夹的名称必须有某种格式。我需要重命名它们并将它们放在这样:

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中的子文件夹以 2nd“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
    }
}

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

3 个答案:

答案 0 :(得分:0)

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

这是否符合您的规格?

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

它不会重命名任何内容,只是吐出一个文件名“将会”的列表。

答案 1 :(得分:0)

我可能会这样做:

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

答案 2 :(得分:0)

在这种初始情况下:

> 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:\Test\2017\08\18\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})_.*','$1'))
        $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:\00_00_Master folder"

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

使用此输出:

>  Q:\Test\2017\08\18\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开头。