【问题标题】:Moving files to a new folder inside their parent based on a criteria根据条件将文件移动到其父级内的新文件夹
【发布时间】:2018-07-09 16:06:42
【问题描述】:

我目前正在使用 Powershell 进行一个项目,对此我真的不是很熟悉。我已经非常接近了,并环顾四周以使我更接近,但我对这个大时代感到难过。

目标是递归搜索一个目录中以“\_7Y_”开头的文件(这是由我编写的另一个脚本完成的,基于文件年龄),并在该文件的父目录中创建一个新的子目录,然后移动它在那里。例如,如果我有~\desktop\old\\_7Y_OldFile.txt,我希望该文件转到~\desktop\old\\_7Y_\\_7Y_OldFile.txt,并且我希望它以递归方式对每个文件执行此操作。

我的脚本当前按预期创建了文件夹,但只选择了一个新文件夹以将项目移动到其中。我认为这是由于 $child 变量只选择了一个值,因为在它移动文件后,脚本会继续执行,但在尝试查找要移动它们的文件时出错。没有手动告诉它每个父母(这个过程最终将是自动化的),我想知道可以做些什么来区分每个 $child 的移动。

我的理解也是,只要我使用-force,我不应该需要先做一个新项目,然后再做一个移动项目,但这也不是我的经验。任何帮助将不胜感激。

对于奇怪的格式和技术,我深表歉意——我一直在边学习边学习 powershell。

[CmdletBinding()]
Param(
[Parameter(mandatory=$true)]
[ValidateScript({Test-Path $_ -PathType 'any'})]
[string] $InputFilePath
)
#this sets the filepath parameter to mandatory, so you will need to input 
your own filepath!

$directoryInfo = Get-ChildItem $InputFilePath -recurse | Measure-Object 
$7Yno = Get-ChildItem $InputFilePath -recurse | Where-Object {$_.Name -like '_7Y_*.*'} | Measure-Object
#These are used as the conditions for the if statements
#directoryInfo gets the number of files in the directory; 7Yno gets the number of files prepended with _7Y_ in the directory

$Confirmation = Read-Host "Are you SURE you want to proceed with this operation? All selected files in the given directory will be moved to new directories! This action is irreversable. Your selected directory is $InputFilePath. Enter 'Yes' to proceed"

if ($Confirmation -eq "Yes") {

    if ($directoryInfo.count -gt 0 -and $7Yno.count -gt 0){   #Check: Files in directory and files prepended with _7Y_ in directory.

    $children = @((Get-ChildItem $InputFilePath -recurse | 
        Where-Object {$_.Name -like "_7Y_*.*"}).directory.fullname | 
            Get-Unique)
    $Files = @(Get-ChildItem $children -recurse | 
        Where-Object {$_.Name -like "_7Y_*.*"})

        foreach($child in $children){
            $7yPath = "$child\_7Y_"
            New-Item -itemtype Directory -path $7yPath -force
        }
        foreach($file in $Files){
            Move-Item $file.fullname -destination $7yPath -force
        }
    }

    if ($directoryInfo.count -gt 0 -and $7Yno.count -eq 0){   #Check: Files in directory, but no files prepended with _7Y_ in directory.
    Read-Host "There are no files prepended with _7Y_ in this directory!"
    }

    if ($directoryInfo.count -eq 0){                            #Check: No files in directory.
    Read-Host "There are no files in this directory!"
    }
}

【问题讨论】:

  • 由于您将文件移动到子目录,因此移动当然是可逆的,没有任何问题。

标签: powershell file-management


【解决方案1】:

IMO 把事情复杂化了。

  • 递归获取带前缀的子项
  • 如果父文件夹名称不等于前缀
    • 检查文件夹是否存在,如果不存在则创建它
    • 将文件移动到文件夹

编辑:简化脚本,只使用一次 "$($_.Directory)\$Prefix"

Push-Location 'X:\Folder\to\start'
$Prefix = '_7Y_'
Get-ChildItem -File -Filter "$Prefix*" -Recurse | 
  Where-Object {$_.Directory.Name -ne $Prefix} |
    ForEach-Object {
      $DirPrefix = "$($_.Directory)\$Prefix"
      If(!(Test-Path $DirPrefix)){
        Md $DirPrefix | Out-Null
      }
      $_ | Move -Destination $DirPrefix

    }

样本树 /F 之前

└───one
    │   _7Y_one.txt
    │
    └───two
        │   _7Y_two.txt
        │
        └───three
            │   _7Y_three.txt
            │
            └───four
                    _7Y_four.txt

运行脚本后

───one
   ├───two
   │   ├───three
   │   │   ├───four
   │   │   │   └───_7Y_
   │   │   │           _7Y_four.txt
   │   │   │
   │   │   └───_7Y_
   │   │           _7Y_three.txt
   │   │
   │   └───_7Y_
   │           _7Y_two.txt
   │
   └───_7Y_
           _7Y_one.txt

解释这条线:

If(!(Test-Path "$($_.Directory)\$Prefix"))
  • 在字符串表达式中处理对象 $_.Directory 的属性时,您必须将其括在 $() 中以明确/强制评估。
  • Test-Path 返回 $true/$false,要反转条件,要么在 If 中使用 -not,要么使用 !(Test-Path ...) 取反

【讨论】:

  • 哦,伙计,那个过滤器正在改变游戏规则。我真的没有想过要那样使用它。我能问一下这里的测试路径是如何工作的吗?过去我遇到过麻烦,即使路径正确,也无法验证它,而无需指定路径类型(请参阅我的参数)。
  • 查看更改/附加的答案。
  • 非常感谢您的回答,以及您在格式化/逻辑方面的帮助。该解决方案在一个测试中有效,但在另一个测试中失败(这是在我的工作机器上),因为当脚本到达移动项目时,因为它试图从 C:\WINDOWS\system32\FILE 移动文件 这是一个类似的问题到我以前的问题......你有没有机会知道为什么会这样?它像以前一样创建文件夹,但为每个项目提供此错误,而不是移动它们:
  • Move-Item : 找不到路径“C:\WINDOWS\system32_7Y_Oldfile.txt”,因为它不存在。在 line:29 char:15 + Move-Item $_ "$($_.Directory)\$Prefix" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (C:\WINDOWS\system32_7Y_WFX07.DOT:String) [Move-Item], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands。移动项目命令
  • 那么您不是故意在系统目录C:\WINDOWS\system32 中工作吗?您正在使用不同的用户/凭据/计划的工作来运行它吗?我建议您插入一个 Push-Location 以在定义的文件夹中开始,最终将参数 -ErrorAction SilentlyContinue 或更短的 -EA 0 添加到 gci。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
相关资源
最近更新 更多