如果我们假设以下伪代码,这将使我的工作更轻松。然后,您可以使用我演示的元素并更改它们以满足您的需求。
- 如果“file.txt”中的字符串包含文件扩展名“txt”,则继续。
- 如果目标文件夹中不存在该文件,则将该文件从源文件夹复制到目标文件夹。
使用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-Path 和Join-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>]
其中<source> 和<destination> 只能是文件夹。
所以,如果你想复制一个文件,你必须这样写:
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"
进一步阅读
这里有一些您可能会觉得有用的参考资料。