将文件夹日期添加到文件夹名称

Add folder date to the foldername

我有一个脚本递归地修改文件夹的 "creation date" 和 "modified date" 以匹配文件夹中最旧和最新的文件(图像文件)。

之后我想添加每个文件夹的创建日期作为其名称的前缀。我已经编写了创建所需名称的代码,但我不知道如何重命名文件夹。

$colFolder = Get-ChildItem -Recurse "." |
             Where-Object {$_.mode -match "d"} |
             Sort-Object Fullname -Descending
$VerbosePreference = "Continue"
foreach ($strFolder In $colFolder) {
  Trap [Exception] {
    Write-Verbose "TRAPPED:" 
    Write-Verbose $_.Exception.Message;
    Write-Verbose $strFolder.FullName
    Continue
  }
  $Path = $strFolder.FullName
  $Folder = Get-Item $Path

  # Get Newest file in folder
  $strOldestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -First 1).LastWriteTime
  $strNewestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -Last  1).LastWriteTime

  # Change the date to match the newest file if it doesn't already
  $Folder.CreationTime = $strOldestTime
  $Folder.LastWriteTime = $strNewestTime

  # add the date as the prefix of the folder (in which the files are)
  $date = $strOldestTime.ToString('yyyy-MM-dd')
  $foldername = $Folder.Name.split("\")[-1]
  Write-Verbose "$date- $foldername"

  #now rename the folder to above name
}

你试过了吗

Rename-Item oldname newname

它适用于简单示例,但可能会破坏嵌套在其他文件夹中的文件夹和递归,因为您可能会在脚本完成之前重命名文件夹。

为了管理,您可以按长度顺序执行它们(根据定义,children 的路径比 parents 的路径长)。这里的好例子:How do I recursively rename folders with Powershell?

重命名文件夹可以像 @onupdatecascade described in 那样完成。

Rename-Item -Path $Folder.FullName -NewName $newname

如果您至少有 PowerShell v3(我强烈推荐),您可以使用参数 -LiteralPath 作为当前文件夹路径,以避免出现特殊字符问题:

Rename-Item -LiteralPath $Folder.FullName -NewName $newname

话虽如此,我想建议对您的代码进行一些改进。

  • Get-ChildItem -Recurse ".":
    Get-ChildItem默认使用当前工作目录,所以"."可以省略。

  • Where-Object {$_.mode -match "d"}:
    您从 Get-ChildItem 获得的对象有一个布尔值 属性 IsContainer 指示您是否有文件夹。无需在模式上使用正则表达式匹配。此外,在 PowerShell v3 和更新版本中,您可以完全省略此步骤,因为 Get-ChildItem cmdlet 有一个仅列出文件夹的附加参数 -Directory

  • 误用hungarian notation(第 1 部分):

    foreach ($strFolder In $colFolder) {
    

    循环变量$strFolder不包含字符串,而是DirectoryInfo对象。这是一个很好的例子,说明为什么我认为匈牙利符号是 space.

  • 的毫无意义的浪费
  • 避免不必要的步骤。

    $Path = $strFolder.FullName
    $Folder = Get-Item $Path
    

    $strFolder 已经包含一个 DirectoryInfo 对象。以上两个语句只是将其转换为路径字符串并返回到 DirectoryInfo 对象。只需将 $Folder 作为循环变量(见上文)。

  • 避免重复代码(尤其是重复的磁盘操作):

    $strOldestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -First 1).LastWriteTime
    $strNewestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -Last  1).LastWriteTime
    

    而不是多次列出和排序子项目运行语句只一次并将结果收集在变量中:

    $items = Get-ChildItem $Path | Sort-Object LastWriteTime
    $strOldestTime = ($items | Select-Object -First 1).LastWriteTime
    $strNewestTime = ($items | Select-Object -Last 1).LastWriteTime
    

    此外,我会简单地在子表达式中展开 LastWriteTime 属性 而不是 运行ning Select-Object

    $strOldestTime = $items | Select-Object -First 1 -Expand LastWriteTime
    $strNewestTime = $items | Select-Object -Last 1 -Expand LastWriteTime
    
  • 误用的匈牙利符号(第 2 部分):
    $strOldestTime$strNewestTime 包含 DateTime 个对象,而不是字符串。

  • $foldername = $Folder.Name.split("\")[-1]:
    Name 属性 已经包含没有路径的文件夹名称,所以没有什么可以分割的。

  • 使用 format operator:

    从日期和当前名称构建新文件夹名称
    $newname = '{0:yyyy-MM-dd} - {1}' -f $oldestTime, $Folder.Name
    
  • 如果您有可能多次 运行 脚本,您可能希望从文件夹名称中删除现有的领先日期,这样日期就不会 "stack":

    $Folder.Name -replace '^\d{4}-\d{2}-\d{2} - '
    

简化代码:

$colFolder = Get-ChildItem -Recurse |
             Where-Object { $_.PSIsContainer } |
             Sort-Object Fullname -Descending

foreach ($folder in $colFolder) {
  $items = Get-ChildItem $folder.FullName | Sort-Object LastWriteTime

  $folder.CreationTime  = $items | Select-Object -First 1 -Expand LastWriteTime
  $folder.LastWriteTime = $items | Select-Object -Last 1 -Expand LastWriteTime

  $newname = '{0:yyyy-MM-dd} - {1}' -f $folder.CreationTime, ($folder.Name -replace '^\d{4}-\d{2}-\d{2} - ')

  Rename-Item -Path $folder.FullName -NewName $newname
}

或(PowerShell v3 及更新版本):

$colFolder = Get-ChildItem -Recurse -Directory |
             Sort-Object Fullname -Descending

foreach ($folder in $colFolder) {
  $items = Get-ChildItem $folder.FullName | Sort-Object LastWriteTime

  $folder.CreationTime  = $items | Select-Object -First 1 -Expand LastWriteTime
  $folder.LastWriteTime = $items | Select-Object -Last 1 -Expand LastWriteTime

  $newname = '{0:yyyy-MM-dd} - {1}' -f $folder.CreationTime, ($folder.Name -replace '^\d{4}-\d{2}-\d{2} - ')

  Rename-Item -LiteralPath $folder.FullName -NewName $newname
}