简体   繁体   English

Powershell - 根据文件名将文件分类到目录中

[英]Powershell - Sort files into directory based on file name

I'm trying to sort my files into unique dictionaries based on the file name and delimiters.我正在尝试根据文件名和分隔符将我的文件分类到唯一的字典中。

File names follow this structure: LocationName-DP-Category-SL文件名遵循以下结构: LocationName-DP-Category-SL

Where... - is the delimiter其中... -是分隔符

  • Location name is a variable length, never has spaces位置名称是可变长度,从不包含空格
  • DP is the two-letter department code DP是两个字母的部门代码
  • Category is a variable length, never has spaces类别是可变长度,从不包含空格
  • S is a single-letter size code S是单字母尺寸代码
  • L is length L是长度

Everything after category is irrelevant, as there is often some extra garble at the end of the filename to ignore.类别之后的所有内容都无关紧要,因为文件名末尾通常有一些额外的乱码要忽略。

I'd like to have a folder structure created and sorted for every found variation of just the LocationName-DP-Category portion of the filepath that looks something like this:我想为文件路径的 LocationName-DP-Category 部分的每个发现的变体创建一个文件夹结构并对其进行排序,如下所示:

  • Parent Folder: LocationName父文件夹:LocationName
  • SubFolder: DP子文件夹:DP
  • SubSubFolder: Category子子文件夹:类别

Trying to keep it less rigid as this runs often on various batches of files.试图让它不那么僵化,因为它经常在不同批次的文件上运行。 Here's what I have:这是我所拥有的:

##GET USER INPUT FROM DIALOG
Add-Type -AssemblyName System.Windows.Forms
$browser = New-Object System.Windows.Forms.FolderBrowserDialog
$null = $browser.ShowDialog()
$path = $browser.SelectedPath + "\"

##SORT ALL FILES
Get-ChildItem -Path $path *-*-*-*-*.* |
  Where-Object BaseName -match '(?<store>\w+)\-+(?<dept>\w+)\-+(?<category>\w+)*.*'|
    Group-Object {$Matches["store"]+'-'+$Matches["dept"]+'-'+$Matches["Category"]}|
      ForEach-Object{mkdir $_.Name;$_.Group|Move-Item -Dest $_.Name}

Would really appreciate the help, been scratching my head on and off for a couple months.非常感谢您的帮助,几个月来一直在摸索我的头。

Thanks谢谢

...initially I also thought about group-object but I think that is not necessary, think this is simpler: ...最初我也考虑过 group-object 但我认为这没有必要,认为这更简单:

#Get Source Files
$files = get-childitem -Path [path]
#Set target root path
$targetPathRoot = "C:\tmp\"
#Loop through array of files
foreach ($file in $files){
    #Split the filename 
    $split = $file.name -split "-"
    #Build the target path
    $newFullPath = $targetPathRoot + $split[0] + '\' + $split[1] + '\' + $split[2]
    #If path exists move item, otherwise create path and move item
    If (Test-Path $newFullPath){
        $null = move-item -Path $file.psPath -Destination $newFullPath
    }
    Else {
        $null = new-item -ItemType Directory -Path $newFullPath -Force
        $null = move-item -Path $file.psPath -Destination $newFullPath
    }
}

Assuming none of the parts 'LocationName', 'DP' or 'Category' contain a hyphen, you could create the new path for the file like this:假设“LocationName”、“DP”或“Category”部分都不包含连字符,您可以像这样为文件创建新路径:

# 'LocationName-DP-Category-S-L-blah.ext' --> LocationName\DP\Category
$_.BaseName -replace '^(\w+-\w{2}-\w+).*', '$1' -replace '-', '\'

Your code can then become然后你的代码可以变成

Add-Type -AssemblyName System.Windows.Forms
$browser = New-Object System.Windows.Forms.FolderBrowserDialog
$null = $browser.ShowDialog()
$path = $browser.SelectedPath
$browser.Dispose()  # remove from memory when done

# the root path for the (new) subfolders and files
$destination = 'X:\SomeWhere'
if (![string]::IsNullOrWhiteSpace($path)) {
    Get-ChildItem -Path $path -Filter '*-*-*-*-*.*' -File | ForEach-Object {
        $subPath   = $_.BaseName -replace '^(\w+-\w{2}-\w+).*', '$1' -replace '-', '\'
        $targetDir = Join-Path -Path $destination -ChildPath $subPath
        # create the new path if it does not already exist
        $null = New-Item -Path $targetDir -ItemType Directory -Force
        # move the file
        $_ | Move-Item -Destination $targetDir
    }
}
else {
    Write-Host "Folder dialog cancelled"
}

Note: On the File System , the New-Item -Path $targetDir -ItemType Directory -Force will either create the new folder, OR return a reference to an existing folder.注意:在File System上, New-Item -Path $targetDir -ItemType Directory -Force将创建新文件夹,或者返回对现有文件夹的引用。 The -Force switch in this case allows you not to have to use Test-Path in this case.在这种情况下, -Force开关允许您在这种情况下不必使用Test-Path Mind you, you should NOT use that technique when dealing with other systems like on registry keys for instance请注意,在处理其他系统(例如注册表项)时,您不应该使用该技术

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM