【问题标题】:Powershell script to find file name in a file and move it to a different directoryPowershell脚本在文件中查找文件名并将其移动到不同的目录
【发布时间】:2019-01-17 14:09:57
【问题描述】:

我目前正在编写一个 powershell 脚本。它应该查看目录中的所有文件并根据它们的内容将它们移动到不同的目录。 现在,在其中一些文件中是关联位图的文件名,例如。 我怎样才能让它在看到关联文件时被移动到同一个文件夹中?

到目前为止,这是我的脚本,它根据文件是否包含 $pattern1 和 $pattern2 中给出的单词将文件分发到 2 个不同的目录。

$source = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\Ursprung_test'
$destination = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\24BHD'
$toDelete = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\ToDelete'
$pattern1 = '24BHD'
$pattern2 = 'RuheEKG'

$hans = Get-ChildItem $source  

foreach($item in $hans) {
    if (Select-String -list -pattern $pattern1 -path $item.fullname) {
        Move-Item -Path $item.fullname -Destination $destination}
        Else {
        Move-Item -Path $item.fullname -Destination $toDelete}


}

在第 31 行的末尾,您会看到相关的位图文件。 我需要脚本将其识别为不同的文件,找到它并将其移动到与包含它的文件所在的目录相同的目录中。

所有帮助将不胜感激!

【问题讨论】:

  • 您能否编辑您的问题并将输入文件的(相关部分)作为格式化文本放入。

标签: powershell parsing


【解决方案1】:

我的猜测是,在移动文件和关联的位图文件之后,您还希望文件包含这些引用文件的新文件路径。

另外,由于您的模式不是真正的正则表达式,我在Select-String 上使用了-SimpleMatch 参数。

这段代码应该可以做到这一点。

$source      = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\Ursprung_test'
$destination = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\24BHD'
$toDelete    = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\ToDelete'
$pattern1    = '24BHD'
$pattern2    = 'RuheEKG'

# create the destination paths if they do not exist
if (!(Test-Path -Path $destination -PathType Container)) {
    Write-Host "Creating folder '$destination'"
    New-Item -Path $destination -ItemType 'Directory' -Force | Out-Null
}
if (!(Test-Path -Path $toDelete -PathType Container)) {
    Write-Host "Creating folder '$toDelete'"
    New-Item -Path $toDelete -ItemType 'Directory' -Force | Out-Null
}

# get an array of full path and filenames.
# if they all have the same extension, it would be wise to add the '-Filter' parameter..
$allFiles = @(Get-ChildItem $source -File | Select-Object -ExpandProperty FullName)

foreach($file in $allFiles) {
    # get the file content as array so we can reuse it and update the line(s) with the new bitmap path(s)
    $content = Get-Content -Path $file

    # first decide on the destination. '-Quit' returns $true or $false
    # if both $pattern1 AND $pattern2 are present, move stuff to $destination
    if (($content | Select-String -Pattern $pattern1 -SimpleMatch -Quiet) -and 
        ($content | Select-String -Pattern $pattern2 -SimpleMatch -Quiet)) {
        $dest = $destination
    }
    else {
        $dest = $toDelete
    }

    # next check if the file contains path(s) for referenced (bitmap) file((s)
    $refCount = 0
    $content | Select-String -Pattern '(^.*)([A-Z]:\\.+$)' -AllMatches | ForEach-Object {
        # each '$_' automatic variable in here holds a MatchInfo object.
        # see: https://docs.microsoft.com/en-us/dotnet/api/microsoft.powershell.commands.matchinfo?view=pscore-6.0.0

        $prefix  = $_.Matches[0].Groups[1].Value   # get the prefix of the line (something like '0619154')
        $refPath = $_.Matches[0].Groups[2].Value   # get the bitmap file path

        if (Test-Path -Path $refPath -PathType Leaf) {
            Write-Host "Moving referenced file '$refPath' to '$dest'"
            Move-Item -Path $refPath -Destination $dest -Force
            # recreate the line to match the new location of the bitmap file
            Write-Host "Updating path in '$file' to '$refPath'"
            $refFile = Split-Path $refPath -Leaf
            $refPath = Join-Path -Path $dest -ChildPath $refFile
            $content[$_.LineNumber -1] = $prefix + $refPath
            $refCount++
        }
        else {
            Write-Warning "Referenced file '$refPath' not found"
        }
        if ($refCount) {
            # we handled referenced files, so write the new content back to the original file
            Set-Content -Path $file -Value $content -Force
        }
    }

    # finally move the file to its new destination
    Write-Host "Moving file '$file' to '$dest'"
    Move-Item -Path $file -Destination $dest -Force
}


编辑

根据您的 cmets:

我已经像下面这样测试过。

我在 D: 驱动器上创建了几个文件夹并将文件放在那里:

+---Fnkraf
    \---Bitmaps
    |       PIC0053.BMP
    |       PIC0057.BMP
    |       PIC0571.BMP
    |       PIC0572.BMP
    |
    \---MasterFiles
            File1.txt
            File2.txt
            File3.txt

Bitmaps 文件夹包含引用的位图文件。
MasterFiles文件夹中,我放了这些文件:

File1.txt
此文件有效,因为它包含两个关键字模式和两个引用的位图文件。两个引用的文件都存在。这些将转到24BHD 文件夹。

24BHD
RuheEKG

01091521
0249153EKG 10 Sekunden
0619154D:\Fnkraf\Bitmaps\PIC0053.BMP
0619155D:\Fnkraf\Bitmaps\PIC0057.BMP
0118410HF

File2.txt
此文件有效,因为它包含两个关键字模式和两个引用的位图文件。其中一个会因为找不到而发出警告。这些将转到24BHD 文件夹。

24BHD
RuheEKG

01091521
0249153EKG 15 Sekunden
0719154D:\Fnkraf\Bitmaps\PIC0571.BMP
0719157D:\Fnkraf\Bitmaps\DOESNOTEXIST.BMP
0118410HG

File3.txt
此文件无效,因为它只包含一个关键字模式。它确实有一个可查找的引用位图文件。这些应该转到toDelete 文件夹

25BHD
RuheEKG

01091521
0249153EKG 17 Sekunden
0619154D:\Fnkraf\Bitmaps\PIC0572.BMP
0118410HG

运行脚本后,结果如下:

+---Fnkraf
    \---24BHD
    |       File1.txt
    |       File2.txt
    |       PIC0053.BMP
    |       PIC0057.BMP
    |       PIC0571.BMP
    |
    +---Bitmaps
    +---MasterFiles
    \---ToDelete
            File3.txt
            PIC0572.BMP

您可以看到目标24BHDtoDelete 文件夹都已创建,主文件File1.txtFile2.txt 连同它们引用的位图文件一起在目标中结束。
File3.txt 失败模式测试按预期进行,并被移至toDelete 文件夹,再次使用引用的位图文件。

现在,如果您打开移动的文本文件,您可以看到引用的文件路径已更新以匹配位图的新位置。

文件 1.txt

24BHD
RuheEKG

01091521
0249153EKG 10 Sekunden
0619154D:\Fnkraf\24BHD\PIC0053.BMP
0619155D:\Fnkraf\24BHD\PIC0057.BMP
0118410HF

其他文件也是如此。 更新的唯一参考是在 File2.txt 中找不到的位图文件:

24BHD
RuheEKG

01091521
0249153EKG 15 Sekunden
0719154D:\Fnkraf\24BHD\PIC0571.BMP
0719157D:\Fnkraf\Bitmaps\DOESNOTEXIST.BMP
0118410HG

希望这能解释一切。

【讨论】:

  • 非常感谢您的回复!我只是不明白这个代码块的作用:if (Test-Path -Path $refPath -PathType Leaf) { Write-Host "Moving referenced file '$refPath' to '$dest'" Move-Item -Path $refPath -Destination $dest -Force # recreate the line to match the new location of the bitmap file Write-Host "Updating path in '$file' to '$refPath'" $refFile = Split-Path $refPath -Leaf $refPath = Join-Path -Path $dest -ChildPath $refFile $content[$_.LineNumber -1] = $prefix + $refPath $refCount++ 你能帮我吗?
  • 它的作用是测试是否可以找到文档中的引用文件(即)C:\Transfer\CardioSoft\RuheEKG_LZRRToCWD\PIC0053.BMP,如果可以,将该文件也复制到目标文件夹。因为在主文件中,文件路径前面有一个数字(即0619154),它也捕获了它。接下来,它会更新文件,因此引用文件的新文件路径也会更新以反映新位置。
  • 好的,非常感谢!你在这里帮了我很大的忙。我还有一件事。每次我执行脚本时,它都会将所有文件移动到“ToDelete”,并给我一条消息“警告:未找到参考文件 PATH”。就好像它在检查和重新定位引用的文件之前将文件移动到“ToDelete”文件夹一样。你有什么想法吗?
  • 不用等,我现在明白了。因为我正在测试这个脚本,所以引用位图文件的路径不正确。有没有办法只使用位图文件名?不是整个路径?
  • @Fnkraf 我已经为我的答案添加了解释和测试。代码更新对主文件中被引用文件的新完整路径和文件名的引用。如果您希望只有引用的文件名(没有路径),只需将行 $content[$_.LineNumber -1] = $prefix + $refPath 更改为 $content[$_.LineNumber -1] = $prefix + $refFile
【解决方案2】:

我想到了很多问题,比如:

  • 文件路径总是在行尾吗?
  • 每个文件是否有一个文件路径,或者是否有更多行包含路径?

假设上述问题的答案是肯定的,则可以从这样的文件中解析文件路径:

foreach($item in $hans) {
    $mat = $item | Select-String -Pattern '.:\\.+'
    foreach($m in $mat) {
        $m.Matches.Value
    }
}

.:\\.+ 是一个正则表达式,它搜索驱动器号、冒号、反斜杠的序列并在同一行中抓取其后面的所有内容。

很多时候,像这样的解析脚本需要一些时间才能正常工作。正则表达式和 Select-String 是您的朋友,但您需要一些时间才能真正了解它们 :-) 在 https://regex101.com/ 上检查/编写您的正则表达式 我在编写正则表达式时大部分时间都使用它。

【讨论】:

    【解决方案3】:

    如果您有一个要匹配的模式列表,并且您可以保证这些模式将始终匹配并且不会意外匹配其他内容,那么您可以使用带有尽可能多的模式匹配和目的地的 switch 语句。

    您可能需要根据源文件名构建目标,在这种情况下,我已经粗略地硬编码了目标路径作为示例:

    $hans = Get-ChildItem $source
    
    foreach($item in $hans)
    {
        switch($item.FullName)
        {
            { $_ -match '24BHD' }        { $destination = 'Z:\24BHD_Destination' }
            { $_ -match 'RuheEKG' }      { $destination = 'Z:\RuheEKG_Destination' }
            { $_ -match 'OtherPattern' } { $destination = 'Z:\OtherCode_Destination' }
    
            default { Write-Host "Match not found for file $($item.FullName)" }
        }
    
        Move-Item $item.FullName $destination
    }
    

    【讨论】:

      猜你喜欢
      • 2016-06-06
      • 1970-01-01
      • 2020-02-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多