【问题标题】:Moving Files to Folders with Powershell and RegEx使用 Powershell 和 RegEx 将文件移动到文件夹
【发布时间】:2017-06-14 14:11:00
【问题描述】:

我编写了以下脚本来根据杂志标题(第一个连字符之前的所有内容)将文件批量处理到文件夹中:

magazine title - year-month.pdf 例如National Geographic - 2017-07.pdf

运行脚本后,杂志从父文件夹移动到新的子文件夹,在本例中为“国家地理杂志”。

三个相关问题:

  1. 即使没有“孤儿”,也会创建“_Orphans”文件夹(第 38 行) 归档到它以供以后手动处理。如何制作文件夹 创建条件?

  2. 重复文件在处理过程中会产生错误消息。脚本继续运行没什么大不了的,但我想以与处理“孤儿”相同的方式处理重复项,使用新的“_Duplicates”文件夹/移动。

  3. 如何注释多行而每行开头不带 # 行(例如,在脚本的顶部)。一定有更优雅的 处理 cmets/文档的方法...?

额外问题:

如果您真的厌倦了等待多 TB 文件副本 您正在像沙漏一样观察进度,任何人都可以提供代码帮助 对于第 10 行所示的分隔符数组(可能是错误的术语/名称)? ID 希望能够指定的不仅仅是我在我的 正则表达式匹配(第 26 行,我花了一天的大部分时间才开始工作)。

$OrigFolder = ".\"
$NewFolder = ".\_Sorted to Move"

# Orphans folder, where files that return null in the regex match will be moved
# Example: file "- title.pdf"
# will be moved to ".\_Orphans" folder

$Orphans = '_Orphans' # Use the underscore to sort the folder to the top of the window

#### How to use an array of values for the delimiters in the regex instead of literals
#### My proposed code, but I am missing how to use the delims in the regex match
#### $delims = "\s-\s" ",\s"\s and\s"

# First count the number of files in the $OrigFolder directory
$numFiles = (Get-ChildItem -Path $OrigFolder).Count
$i=0

# Tell the user what will happen
clear-host;
Write-Host 'This script will copy ' $numFiles ' files from ' $OrigFolder ' to _Sorted to Move'

# Ask user to confirm the copy operation
Read-host -prompt 'Press enter to start copying the files'

# Regex to match filenames
$Regex = [regex]"(?:(.*?)\s-)|(?:(.*?),\s)|(?:(.*?)\sand\s)"

# Loop through the $OrigFolder directory, skipping folders
Get-ChildItem -LiteralPath $OrigFolder | Where-Object {!$_.PsIsContainer} |
    ForEach-Object {
        if($_.BaseName -match $Regex){
        $ChildPath = $_.BaseName -replace $Regex

#Caluclate copy operation progress as a percentage
[int]$percent = $i / $numFiles * 100

# If first part of the file name is empty, move it to the '_Orphans' folder
if(!$Matches[1]){
    $ChildPath = $Orphans}
else {
    $ChildPath = $Matches[1]
    }

# Generate new folder name
$FolderName = Join-Path -Path $NewFolder -ChildPath ($ChildPath + ' Magazine')

# Create folder if it doesn't exist
    if(!(Test-Path -LiteralPath $FolderName -PathType Container)){
    $null = New-Item -Path $FolderName -ItemType Directory}

# Log progress to the screen
Write-Host "$($_.FullName) -> $FolderName"

# Move the file to the folder
Move-Item -LiteralPath $_.FullName -Destination $FolderName

# Tell the user how much has been moved
Write-Progress -Activity "Copying ... ($percent %)" -status $_  -PercentComplete $percent -verbose
$i++
    }
}

Write-Host 'Total number of files in '$OrigFolder ' is ' $numFiles
Write-Host 'Total number of files copied to '$NewFolder ' is ' $i
Read-host -prompt "Press enter to complete..."
clear-host;

【问题讨论】:

  • 多行cmets可以用<##>这样包裹<# your multi line comment here #>

标签: powershell


【解决方案1】:

Q1:我在我的机器上使用遵循相同命名方案的 PDF 测试了您的脚本,它没有创建 Orphans 文件夹或移动我的 Orphan PDF。我注意到你在 foreach 之后立即有一个 if ($_.BaseName -match $Regex) 。在里面你正在寻找孤儿,但孤儿不会进入这个 if 块,因为它们不匹配正则表达式。在伪代码中,你的结构应该是这样的:

    foreach{
          if (match)
               {$childpath $_.BaseName -replace $Regex}
          else 
               {Childpath = $Orphans}
          Create your folders and do your moves.
}

Q2:尝试,捕获块:https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/05/weekend-scripter-using-try-catch-finally-blocks-for-powershell-error-handling/

Q3:您可以通过将多行括在 对中来注释多行。

<#
 How to use an array of values for the delimiters in the regex instead of literals
 My proposed code, but I am missing how to use the delims in the regex match
 $delims = "\s-\s" ",\s"\s and\s"
#>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2021-12-02
    相关资源
    最近更新 更多