【问题标题】:move files with specific extension to folder in higher hierarchy将具有特定扩展名的文件移动到更高层次结构的文件夹
【发布时间】:2017-08-09 12:56:52
【问题描述】:

我所有的文件都在特定的文件夹中:

17\1\1\PRO
17\1\2\PRO
17\2\1\PRO
xx\xx\xx\PRO
  • 17 是年份(所以明年 18 等)
  • 第一个 1 是指定案例编号的文件夹(最多 100 个)。
  • 第二个1是箱号上的子零件。

最后 1 个文件夹中有一个文件夹 PRO,所有数据都驻留在其中。

我们需要移动这些文件,但这些文件需要保留在各自的“PRO”文件夹中。

例如:

  • 17\1\1\pro\xxx\www\ 中的文件需要转到17\1\1\pro\movies
  • 17\2\2\pro\xxdfsdf\eeee\ 中的文件需要转到17\2\2\pro\movies

如果有要移动的文件,应该创建电影文件夹。

我需要获取文件全名的一部分并将该文件移动到“电影”文件夹中。问题是我不知道如何拆分全名,添加 \movies 并将文件移动到那里。

这是我目前的代码:

Get-ChildItem -Path $mypath -Recurse -File -Filter $extension | select $_Fullname |
Move-Item -Force -Destination ($_Fullname.Split("pro"))

【问题讨论】:

    标签: powershell move get-childitem


    【解决方案1】:

    如果目标始终是“文件目录的祖父目录的电影子目录”,您可以构建相对于文件位置的目标路径:

    Get-ChildItem ... | ForEach-Object {
        $dst = Join-Path $_.Directory '..\..\movies'
        if (-not (Test-Path -LiteralPath $dst -PathType Container)) {
            New-Item -Type Directory -Path $dst | Out-Null
        }
        Move-Item $_.FullName -Destination $dst
    }
    

    如果PRO 目录是您的锚点,您可以使用这样的正则表达式替换:

    Get-ChildItem ... | ForEach-Object {
        $dst = $_.Directory -replace '^(.*\\\d+\\\d+\\\d+\\PRO)\\.*', '$1\movies'
        if (-not (Test-Path -LiteralPath $dst -PathType Container)) {
            New-Item -Type Directory -Path $dst | Out-Null
        }
        Move-Item $_.FullName -Destination $dst
    }
    

    【讨论】:

    • 嗯,祖父母目录并不总是确定的。 pro 文件夹内可能有数千个目录,每个子目录都拆分为多个目录。永远无法确定有多少子文件夹
    • 如果是这种情况,只需将目标子目录作为参数输入到 cmdlet/函数中。
    • 您需要在第二个版本的移动前插入一个If (!(Test-Path $dst)){md $Dst|out-Null}。 +1。
    • @LotPings 确实如此。我错过了“如果有文件要移动,应该创建电影文件夹”部分。感谢您的提醒。
    【解决方案2】:

    如果你不知道有多少个目录,我会这样做:

    Get-ChildItem -Path $mypath -Recurse -File -Filter $extension | ForEach-Object {
        if ($_.FullName.IndexOf('\PRO\') -gt 0) {
            $Destination = Join-Path -Path $_.FullName.Substring(0,$_.FullName.IndexOf('\PRO\') + 5) -ChildPath 'movies';
            New-Item $Destination -ItemType Directory -ea Ignore;
            $_ | Move-Item -Destination $Destination;
        } else {
            throw ("\PRO\ path not found in '$($_.FullName)'");
        }
    }
    

    只要您的路径只有一次\pro\,这将正常工作。如果他们不止一次像customer\pro\17\pro\17\1\1\pro\xx\yy\zz\www 一样拥有它并且您需要最后一个索引,那么使用$_.FullName.LastIndexOf('\pro\')

    如果您在.\pro\movies\ 所在的目录之前和之后都有\pro\ 目录,那么您就有麻烦了。您可能必须找到不同的参考点。

    【讨论】:

    • 整个路径结构中只有 1 个 pro,所以这会起作用。
    • 这将在适当的位置创建一个 file movies,其中包含移动文件的内容。您应该首先对文件夹 $Destination 进行测试路径,然后使用它自己的名称移动文件,以检查它是否已经存在,以免覆盖其他子文件夹中的相同名称。
    • 在 move-item 行前面插入 If (!(Test-Path $Destination)){md $Destination|out-Null}
    • @LotPings 很公平,我错过了。
    【解决方案3】:

    带有一组文件夹

    17\1\1\PRO
    17\1\2\PRO
    17\2\1\PRO
    

    你可以试试下面的

    $RootPaths = Get-ChildItem -Path C:\folder\*\*\*\pro
    

    $RootPaths 然后将包含上面提到的所有 3 个路径,下面的代码会将所有文件移动到适当的目录。

    ForEach( $Path in $RootPaths)
    {
        $Movies = Join-Path $Path -Child "Movies"
        If( -not (Test-Path $Movies ) ) { New-Item -Path $Movies -ItemType Directory }
    
        Get-ChildItem -Path $Path -Recurse -File -Filter $Extension | 
            Move-Item -Path $_.FullName -Destination "$( $Path )\Movies"
    }
    

    这样,您的文件向下多少级都没有关系。它们总是被移动到同一个目录。

    【讨论】:

    • IMO 你应该从Move-Item 中删除-Path,因为它已经从管道接收文件对象。
    • 您不能使用 $rootpaths,因为您事先不知道根路径是什么。这取决于您所在的子目录:17\1\1\pro 收集下面的所有内容 17\2\1\pro 收集下面的所有内容
    • Michael,在 Powershell 中,星号字符可用于指代所有文件夹。这意味着$RootPaths 将包含所有具有 pro 文件夹的文件夹,从根目录向下 2 级。
    • 上述缺陷仍然存在,并且您的脚本也遇到了同样的问题 - 如果未首先创建电影文件夹,则文件将移动到名为 movies。
    • 好的,添加了目录的创建。很好发现。
    猜你喜欢
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多