用于将文件移动到文件夹的Powershell脚本-如何从$newFolder中删除连字符?

用于将文件移动到文件夹的Powershell脚本-如何从$newFolder中删除连字符?,powershell,regex-greedy,progress-indicator,Powershell,Regex Greedy,Progress Indicator,根据文件名的第一部分,我有很多文件要归档到文件夹中。文件名->文件夹名由特定字符分隔:[-][,][和]。例如: 第一个文件名-2016-04.pdf 第二个文件名和另一个名称.mp3 第三.jpg 第四个文件名,2016.pdf 我希望生成的文件夹名称不包括[\s-][,\s][\sand\s]部分 这是我的脚本,除了文件夹名称包含我不想要的内容外,它是有效的,例如: 第一个文件夹名- 第四个文件名 我认为这与我的正则表达式匹配贪婪地包含连字符有关(特别是),但我不确定如何格式化查询和创建SU

根据文件名的第一部分,我有很多文件要归档到文件夹中。文件名->文件夹名由特定字符分隔:[-][,][和]。例如:

第一个文件名-2016-04.pdf 第二个文件名和另一个名称.mp3 第三.jpg 第四个文件名,2016.pdf

我希望生成的文件夹名称不包括[\s-][,\s][\sand\s]部分

这是我的脚本,除了文件夹名称包含我不想要的内容外,它是有效的,例如:

第一个文件夹名- 第四个文件名

我认为这与我的正则表达式匹配贪婪地包含连字符有关(特别是),但我不确定如何格式化查询和创建SUNBESQUENT文件夹名称

此外,用“######”(类似于进度指示器)注释掉的内容也不起作用。如果您有任何建议,请发表评论。我根本不是一个程序员

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

# Orphans folder, where files that return null in the regex match will be moved
# Example: file "- title.mp4"
# will be moved to ".\Sorted\_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 o 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*-)|(^\s*(.*?),)|(^\s*(.*?)\s*and\s)"

    # Loop through the $OrigFolder directory, skipping folders
Get-ChildItem -LiteralPath $OrigFolder | Where-Object {!$_.PsIsContainer} |
    ForEach-Object {
        if($_.BaseName -match $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

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

非常感谢StackOverflow用户的帮助和我在上面拼凑的代码片段。

下面的正则表达式应该可以找到任何不需要的分隔符(使用非捕获组):

现在,您所要做的就是使用
-用该正则表达式替换
,以摆脱它们:

if($_.BaseName -match $Regex)
{
    $ChildPath = $_.BaseName -replace $Regex

    # copy...
}
另外,请看一下:

如果未显示进度条,请检查 $ProgressPreference变量。如果该值设置为SilentlyContinue, 进度条不显示。有关Windows的详细信息,请参见 PowerShell首选项,请参阅关于首选项变量。参数 cmdlet的属性对应于ProgressRecord类的属性 (系统、管理、自动化、进度记录)。欲了解更多信息, 请参阅Windows PowerShell软件中的ProgressRecord主题 开发工具包(SDK)


下面是将my.pdf文件(杂志)移动到以杂志标题命名的子目录的完整脚本。感谢jisaak(Martin Brandl)帮助我解决regex问题。将“杂志”添加到新文件夹的解决方案位于第46/47行。对大多数人来说可能是显而易见的,但我花了一个小时才弄明白

我很想得到关于简化代码和修复缩进等方面的建议。我还不了解Powershell的风格,这是我的第一次尝试

$OrigFolder = "T:\Magazines"
$NewFolder = "T:\Magazines\_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 ".\Sorted\_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 o 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 and append ' Magazine' to the 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;

我已经为我的多媒体文件和图片修改了脚本,你不知道这会为我节省多少时间。再次感谢你,马丁

谢谢你的快速回复。我理解您试图向我展示的内容,但脚本无法将PDF移动到各个文件夹。相反,所有内容都被发送到“孤儿”文件夹,我想是因为正则表达式无法正确捕获名称?也许我把replace语句放错地方了……我把它放在了第31行“if($\u.BaseName-match$Regex)”之后。谢谢你对write progress函数的建议。修正了。我只是删除了目录名中的三个delimter和它们之间的空格。您只想保留名称的一部分吗?我想保持所有内容都符合delimeter,因此“Time-2016-03.pdf”成为文件夹名称“Time”。我想在创建的每个文件夹中添加“杂志”。所以文件夹变成了“时代杂志”,里面有文件“Time-2016-03.pdf”,等等。好的,所以我在你建议的正则表达式中添加了一个捕获组:
$OrigFolder = "T:\Magazines"
$NewFolder = "T:\Magazines\_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 ".\Sorted\_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 o 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 and append ' Magazine' to the 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;