【问题标题】:Read a file and then based on file content names, move the file from one folder to another using Powershell script读取文件,然后根据文件内容名称,使用 Powershell 脚本将文件从一个文件夹移动到另一个文件夹
【发布时间】:2021-05-24 23:01:40
【问题描述】:

我需要读取一个以文件名作为内容的文件(例如 file.txt)。文件名由唯一字符分隔(例如“@”)。所以我的 file.txt 看起来像:

ABC.txt@
CDE.csv@
XYZ.txt@

我需要根据其扩展名逐行阅读其内容。我有 1 个源文件夹和 1 个目标文件夹。以下是我需要实现的场景:

If extension = txt then 
    check if that file name exists in destination_folder1 or destination_folder2
        if that file exists then
            copy that file from source_folder1 to destination_folder1
        else delete that file from destination_folder1
Else display msg as "Invalid file"

我是 powershell 脚本的新手。有人可以帮忙吗?提前致谢。

【问题讨论】:

  • 添加你的努力,即使它可能是错误的,也可能会在这个问题上得到支持
  • Get-ChildItem C:\somepath | %{ if($_.Extension -eq ""){ ## test-path ##copy } else { ##do something } } 一些骨架代码
  • 新手很好,但这意味着您需要跟上节奏。 Youtube 是你的朋友。 Beginning PowerShellPowerShell file and folder management 您所追求的所有内容都在 PowerShell 帮助文件和帮助文件示例中。 Get-ChildItemMove-Item 和条件匹配。你有你的伪代码,一步一步地工作。

标签: powershell


【解决方案1】:

如果我们假设以下伪代码,这将使我的工作更轻松。然后,您可以使用我演示的元素并更改它们以满足您的需求。

  1. 如果“file.txt”中的字符串包含文件扩展名“txt”,则继续。
  2. 如果目标文件夹中不存在该文件,则将该文件从源文件夹复制到目标文件夹。

使用Get-Content 读取文本文件。

Get-Content .\file.txt 

Get-Content 逐行处理文件。这会产生一些后果:

  • 输入文本文件中的每一行都会触发我们的代码。
  • 每次我们的代码触发时,都会有如下所示的输入:ABC.txt@
  • 我们可以集中精力解决一条线的问题。

如果我们需要评估字符串,我建议使用regular expressions

请记住,我们是在文本文件中的一行操作:

ABC.txt@

我们需要检测文件扩展名。

一个好的起点是字符串的结尾。

在正则表达式中,字符串的结尾用$表示

让我们从这里开始吧。

到目前为止,这是我们的正则表达式:

$

接下来有用的是我们是否考虑了那个 @ 符号。我们可以通过在$之前添加它来做到这一点

@$

如果有不同的字符,我们会添加:;$ 请记住,正则表达式中有保留字符。所以我们可能需要escape某些字符加上反斜杠:\$$


现在我们必须考虑文件扩展名。

我们有三个字母,我们不知道它们是什么。

正则表达式有一个特殊的转义序列(称为字符类),可以匹配任何字母:\w

让我们添加其中的三个。

\w\w\w@$

现在,在制作正则表达式时,最好限制我们要查找的文本。

作为人类,我们知道我们正在寻找 .txt@ 但是,到目前为止,计算机只知道 txt@ 没有点。因此它将接受.txt@.xlsx@anythingGoes@ 作为匹配项。我们限制了字符串的右侧。现在让我们限制左侧。

我们只对三个字符感兴趣。左侧以. 为界,所以让我们将其添加到我们的正则表达式中。我还将提到句点是正则表达式中的保留字符。所以,我们将不得不逃脱它。

\.\w\w\w@$

所以如果我们正在查看这样的文本

ABC.txt@

那么我们的正则表达式会输出这样的文本

.txt@

现在,.txt@ 是一个相当不错的结果。但是我们可以通过将结果限制为文件扩展名来简化我们的工作。

有几种方法可以做到这一点。但我建议使用正则表达式组。

我们通过用括号将目标括起来来创建一个组。

\.(\w\w\w)@$

这会产生如下输出:

txt

从这里,我们可以像if txt = txt一样进行直观的比较。


另一个难题是测试文件是否已经存在。为此,我们可以使用Test-PathJoin-Path cmdlet。

$destination = ".\destination 01" 

$exampleFile = "ABC.txt"

$destinationFilePath = Join-Path -Path $destination -ChildPath $exampleFile

Test-Path -Path $destinationFilePath


有了这些概念,就可以编写一个工作示例了。

# Folder locations. 
$source = ".\source"
$destination = ".\destination 01" 

# Load input file. 
Get-Content .\file.txt | 
  Where-Object {
    # Enter our regular expression. 
    # I've added an extra group to capture the file name. 
    # The $matches automatic variable is created when the -match comparison operator is used. 
    if ($_ -match '([\w ]+\.(\w\w\w))@$')
    {
        # Which file extensions are we interested in processing? 
        # Here $matches[2] represents the file extension: ex "txt". 
        # We use a switch statement to handle each type of file extension. 
        # Accept new file types by creating new switch cases. 
        switch ($matches[2])
        {
          "txt"   {$true; Break}
         #"csv"   {$true; Break}
         #"pdf"   {$true; Break}
          default {$false}
        }
    }
    else { $false }
  } | 
  ForEach-Object {
    # Here $matches[1] is the file name captured from the input file. 
    $sourceFilePath      = Join-Path -Path $source      -ChildPath $matches[1]
    $destinationFilePath = Join-Path -Path $destination -ChildPath $matches[1]
    $fileExists          = Test-Path -Path $destinationFilePath

    # Copy the source file to the destination if the destination doesn't exist. 
    if (!$fileExists)
    {  Copy-Item -Path $sourceFilePath -Destination $destinationFilePath  } 
  }


关于复制项目的注意事项

Copy-Item 有已知问题。

您可以替换为robocopy,这样更可靠。

robocopy 语法是:

robocopy <source> <destination> [<file>[ ...]] [<options>]

其中&lt;source&gt;&lt;destination&gt; 只能是文件夹。

所以,如果你想复制一个文件,你必须这样写:

robocopy .\source ".\destination 01" ABC.txt 

我们可以使用 Start-Process 和我们已经拥有的变量来调用 robocopy。

    # Copy the source file to the destination if the destination doesn't exist. 
    if (!$fileExists)
    {  
      Start-Process -FilePath "robocopy.exe" -ArgumentList "`"$source`" `"$destination`" `"$($matches[1])`" /unilog+:.\robolog.txt" -WorkingDirectory (Get-Location) -NoNewWindow 
    } 

使用 Get-ChildItem

您使用 file.txt 作为输入。如果您想收集光盘上的文件列表,可以使用Get-ChildItem


多重条件

您编写了“destination_folder1 destination_folder2”。如果你需要多个条件,你可以用三样东西来构造它。

使用if statement。在测试条件里面,可以用logical -or添加多个条件,也可以group statements一起添加,这样更容易阅读。


功能

如果您需要移动一段代码,可以使用function。只需记住为函数的输入创建参数。然后调用不带括号或逗号的 PowerShell 函数:

# Calling a PowerShell function. 
myFunction parameterOne parameterTwo parameterThree 

写入输出

您可以使用Write-Output 向控制台发送文本。

Write-Output "Invalid File" 

进一步阅读

这里有一些您可能会觉得有用的参考资料。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多