【问题标题】:Create folders and move files to folder structure based on filename根据文件名创建文件夹并将文件移动到文件夹结构
【发布时间】:2019-02-08 18:57:06
【问题描述】:

我有一个包含视频文件的文件夹,我需要为每个文件创建一个文件夹,其中文件夹名称与文件相同(减去文件扩展名),并将该特定文件移动到它的关联文件夹中。

最终结果应该消除根目录下的所有文件,并且每个文件夹都应该包含一个文件。

示例文件夹开始时应如下所示:

  • c:\videos\video1.avi
  • c:\videos\video2.mov
  • c:\videos\video3.mkv

然后看起来像这样:

  • c:\videos\video1\video1.avi
  • c:\videos\video2\video2.mov
  • c:\videos\video3\video3.mkv

除了将文件移动到相关文件夹的最后一步之外,一切正常。

在第二个ForEach 中,我尝试使用第一个循环中使用的$basename 变量指定目标路径。这不起作用,因为它会导致将所有文件移动到一个文件夹中,这是从第一个 Foreach 循环传递给 $basename 变量的最后一个对象。

foreach ($filename in $VideoFiles) {
    Move-Item -Path \\server1\Video\Staging\$filename -Destination \\server1\Video\Staging\$basename -verbose 
}

这种方法是有道理的,但以我有限的知识和经验,我想不出另一种方法来实现我的目标。我开始研究嵌套 ForEach 循环,但我猜有一种更简单的方法可以实现这一点。

我在第二个循环中尝试了以下命令

Move-Item -Path \\server1\Video\Staging\$filename -Destination \\server1\Video\Staging\$filename -verbose

当然,该变量存储的是文件名(包括扩展名)并且没有移动任何文件。

任何帮助将不胜感激..!

Get-ChildItem -Path \\server1\video\staging | ForEach-Object {$_.basename} | Out-File \\server1\video\videonames.txt

$VideoNames = Get-Content \\server1\video\videonames.txt

Get-ChildItem -Path \\server1\video\staging | ForEach-Object {$_.name} | Out-File \\server1\video\videosfiles.txt

$VideoFiles = Get-Content \\server1\video\videosfiles.txt

foreach ($BaseName in $VideoNames) {
    New-Item -ItemType Directory -Path \\server1\Video\Staging\$BaseName 
}

foreach ($filename in $VideoFiles) {
    Move-Item -Path \\server1\Video\Staging\$filename -Destination \\server1\Video\Staging\$basename -verbose 
}

【问题讨论】:

  • 请保持您的问题简短明了。
  • 不确定所有这些代码应该做什么,但一个简单的带有for /f 循环的五行或六行批处理文件可以完全满足您的要求。即使使用 PS,您也将事情变得过于复杂 - 只需创建文件夹并移动文件,然后移动到下一个文件夹和文件。您不需要多个循环。

标签: powershell


【解决方案1】:

我会进一步简化这一点,并在此过程中通过使用 Join-Path cmdlet 来消除创建错误路径名的风险,如下所示:

$Source = '\\server1\Video\Staging'

(Get-ChildItem -Path $Source -File) | ForEach-Object {
    $destination = Join-Path -Path $Source -ChildPath $_.BaseName

    if(!(Test-Path $destination)){
        New-Item -ItemType Directory -Path $destination | Out-Null
    }
    $_ | Move-Item -Destination $destination
}

【讨论】:

    【解决方案2】:

    这可能不是最好的方法,但它完全符合我的需要。当文件名和通配符满足要求时,我过于专注于使用确切的文件名,包括 .ext。

    #Creates a text file list of the file names and defines a variable for it.
    Get-ChildItem -Path \\server1\video\staging | ForEach-Object {$_.basename} | Out-File \\server1\video\videonames.txt
    $VideoNames = Get-Content \\server1\video\videonames.txt
    
    #Creates the folder structure based on file names
    $Folder = foreach ($BaseName in $VideoNames){
        New-Item -ItemType Directory -Path \\server1\Video\Staging\$BaseName   
    }
    
    #Moves each file in the folder with the same name.
    foreach ($File in $VideoNames){
        Move-Item -Path \\server1\Video\Staging\$file.* -Destination \\server1\Video\Staging\$file -verbose
    }
    

    【讨论】:

      【解决方案3】:

      你的回答很好,但是没有必要在其中创建一个包含属性名称的文件。

      您可以只选择循环内的BaseName 属性,这意味着您只需要一个foreach

      $Source = '\\server1\Video\Staging'
      
      foreach ($File in Get-ChildItem -Path $Source) {
          $FileBaseName = $File.BaseName
      
          if(!(Test-Path $Source\$FileBaseName)){
              New-Item -ItemType Directory -Path $Source\$FileBaseName -WhatIf
          }
          Move-Item -Path $Source\$FileBaseName.* -Destination $Source\$FileBaseName -WhatIf
      }
      

      注意:当您希望代码执行操作时,请删除 -WhatIf

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多