使用Powershell和RegEx将文件移动到文件夹

时间:2017-06-14 14:11:01

标签: powershell

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

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

在运行脚本之后,杂志将从父文件夹移动到新的子文件夹,在本例中为#34;国家地理杂志"。

三个相关问题:

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

  2. 重复文件在处理过程中会生成错误消息。脚本继续运行并不是什么大不了的事,但我想以同样的方式处理重复事件“孤儿'处理,新的" _Duplicates"文件夹/移动。

  3. 如何在每个行的开头没有#的情况下注释多行 line(例如,在脚本的顶部)。必须有一个更优雅 处理意见/文件的方式......?

  4. 奖金问题:

    如果您真的无聊等待多TB文件副本 你像小时玻璃一样看着进展,任何人都可以帮忙解决问题 对于一系列分隔符(可能是错误的术语/名称),如第10行所示?我' d 喜欢能够指定的不仅仅是我在我使用的硬编码连字符 正则表达式匹配(第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;
    

1 个答案:

答案 0 :(得分:0)

Q1:我在我的机器上测试了你的脚本,其PDF格式遵循相同的命名方案,并且没有创建Orphans文件夹或移动我的孤立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/

问题3:您可以将多行包含在< ##>中进行注释对

<#
 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"
#>