【问题标题】:Issue with foreach + get-childitemforeach + get-childitem 的问题
【发布时间】:2018-12-20 20:35:10
【问题描述】:

我正在编写一个脚本来组织我的媒体。在添加到我的媒体中心之前,我将文件下载到一个目录中以容纳它们。 例如,如果我有一个名为 Breaking.Bad.S01E01.DVDRip.XviD-ORPHEUS.avi 的文件,我希望脚本获取节目名称,检查 S01 上的季节并将该文件移动到另一个磁盘中的文件夹,例如 e:\series\breaking bad\season 01 到目前为止,它会检查文件是否调用 s01e01 或 S01E01 或 s01.e01 或 S01.E01 并返回 Breaking Bad\Season 01,创建移动到的路径和移动操作本身

我有该脚本的一部分,但我无法让 get-childitem 与 foreach 一起使用。

这是我目前所拥有的以及我得到的错误:

代码

$FilesList = Get-ChildItem -name -recurse -include *.mkv,*.mp4,*.srt,*.avi
$FilesList

foreach ($FL_Item in $FilesList)
    {
    $SeriesName = ($FL_Item.BaseName -split '\.s\d')[0].Replace('.', ' ')
    $SE_Info = $FL_Item.BaseName.Split('.')[-3] -split 'e'`

    $Season = $SE_Info[0] -replace 's', 'Season '
    #$Episode = 'Episode{0}' -f $SE_Info[1]

    $SeriesName
    $Season
    #$Episode

    $SeriesDirectory = Join-Path -Path "$SeriesName" -ChildPath "$Season"
    $SeriesDirectory

    #$MoverArchivo = move-item -path $FileName -destination e:\series\$SeriesDirectory
    #$MoverArchivo

    ''
    }

我得到的输出

Breaking.Bad.S01E01.DVDRip.XviD-ORPHEUS.avi
Breaking.Bad.S01E01.DVDRip.XviD-ORPHEUS.spa.srt
Breaking.Bad.S04E01.Box.Cutter.720p.hdtv.x264-orenji.mkv
Breaking.Bad.S04E01.Box.Cutter.720p.hdtv.x264-orenji.spa.srt
Breaking.Bad.S05E15.720p.HDTV.x264-EVOLVE.mkv
Breaking.Bad.S05E15.720p.HDTV.x264-EVOLVE.spa.srt
Path Of Blood (2018) [WEBRip] [1080p] [YTS.AM]\Path.Of.Blood.2018.1080p.WEBRip.x264-[YTS.AM].mp4
They Shall Not Grow Old (2018) [BluRay] [1080p] [YTS.AM]\They.Shall.Not.Grow.Old.2018.1080p.BluRay.x264-[YTS.AM].mp4

错误

You cannot call a method on a null-valued expression.
At D:\shared\temp\test3.ps1:8 char:5
+     $SE_Info = $FL_Item.BaseName.Split('.')[-3] -split 'e'
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Cannot index into a null array.
At D:\shared\temp\test3.ps1:10 char:5
+     $Season = $SE_Info[0] -replace 's', 'Season '
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray


Join-Path : Cannot bind argument to parameter 'Path' because it is an empty string.
At D:\shared\temp\test3.ps1:17 char:37
+     $SeriesDirectory = Join-Path -Path "$SeriesName" -ChildPath "$Sea ...
+                                        ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Join-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Join
   PathCommand

有什么想法可能是错的吗?

【问题讨论】:

  • 我认为数字版权管理可能是错误的:P
  • 最后两个文件名的格式不同,因此拆分不适用于它们。

标签: powershell


【解决方案1】:

您在第一行中使用了Get-ChildItem-name 参数:

$FilesList = Get-ChildItem -name -recurse -include *.mkv,*.mp4,*.srt,*.avi

这意味着它将只返回文件名作为字符串。

稍后,在您的循环中,您使用BaseName 属性访问每个元素,该属性是FileInfo 对象的属性,而不是字符串。因此,$FL_Item.BaseName 返回一个空字符串,您会得到如图所示的错误。

只需删除-name,它应该可以工作(或者至少您不会收到这些错误)。

【讨论】:

    【解决方案2】:

    我会使用带有(命名的)捕获组的正则表达式来 grep 系列、季节和剧集编号。
    查看在 regex101.com 上实时运行的 RegEx

    ## Q:\Test\2018\12\20\SO_53875674.ps1
    $DstBase = "E:\series"
    Get-ChildItem -Include *.mkv,*.mp4,*.srt,*.avi -Recurse -File|
      Where-Object BaseName -match "^(?<Series>.*?)\.?S(?<Season>\d{1,2})\.?E(?<Episode>\d{2})"|
        ForEach-Object {
          $Destination = "{0}\{1}\Season {2:00}\" -f $DstBase,$Matches.Series.replace('.',' ').Trim(),[int]$Matches.Season
          if (!(Test-Path $Destination)){MD $Destination -Force | Out-Null}
          "Moving file [{0}] to [{1}]" -f $_.FullName,$Destination
          $_ | Move-Item -Destination $Destination -Force
        }
    

    运行脚本后的示例树(包含上述数据):

    > tree /F
    └───series
        └───Breaking Bad
            ├───Season 01
            │       Breaking.Bad.S01E01.DVDRip.XviD-ORPHEUS.avi
            │       Breaking.Bad.S01E01.DVDRip.XviD-ORPHEUS.spa.srt
            │
            ├───Season 04
            │       Breaking.Bad.S04E01.Box.Cutter.720p.hdtv.x264-orenji.mkv
            │       Breaking.Bad.S04E01.Box.Cutter.720p.hdtv.x264-orenji.spa.srt
            │
            └───Season 05
                    Breaking.Bad.S05E15.720p.HDTV.x264-EVOLVE.mkv
                    Breaking.Bad.S05E15.720p.HDTV.x264-EVOLVE.spa.srt
    

    【讨论】:

    • 嗨,下面是我的回答
    • @MarianoCandial 虽然您的 NON 答案同时被删除,但我仍然可以阅读它。我注意到Big Bang Theory 文件只有一个位置用于季节编号,这会将它们排除在 Where-Object 中 - 我在 RegEx 中更改了它。系列名称以空格结尾的文件也会导致错误。该目录在创建时没有尾随空格,但仍附加到变量$Destination。包括一个.Trim() 来解决这个问题。顺便说一句,如果答案解决了您的问题,您应该考虑accept the answer
    • 谢谢,我会检查的。很抱歉没有接受您的回答,这是我第一次在 stackoverflow 中。
    • 如果你想有两个地方的 ALL 赛季号码,则需要另一个更改,如果文件不同,ATM 你可能会得到几个目录Season 4/Season 04 .
    • 是的!我看到了,它应该总是强制将它重写为第 04 季,因为这就是我组织它的方式。我正在研究如何显示移动项目的进度条或至少显示它的结果。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多