PowerShell在扩展之前将字符串插入文件名中

发布于 2025-01-21 13:54:28 字数 878 浏览 0 评论 0原文

我需要在文件上做很多事情的一般事情是创建/引用文件的备份版本。例如,我可能想拥有一个文件的日期/时间戳版本,以便我可以在整个脚本中引用原始报告和备份版本:

$now = $(Get-Date -format "yyyy-MM-dd__HH-mm")
$ReportName = "MyReport-en.csv"
$Backups = "D:\Backups\Reports"

我发现使用-join++始终在日期/时间戳记之前插入一个空间:

$ReportBackup = "$Backups\$($ReportName -split ".csv")" + "_$now.csv"
$ReportBackup = "$Backups\$($ReportName -split ".csv")" -join "_$now.csv"

我找到了一种方法,但是对于Triple $和重复.csv

$ReportBackup = "$Backups\$($($ReportName -split ".csv")[0])$_now.csv"

哪个导致:

$ReportBackup => D:\Backups\Reports\MyReport-en_2022-04-15__07-55.csv

您能想到更简单/更清洁的方法来实现在扩展前插入文本的通用目标,而没有三重$或扩展的重复? (“使用$ name =“ myReport-en”“不是那么有用,因为我经常读取文件对象并获得扩展名的名称。

A general thing that I need to do a lot with files is to create/reference a backup version of a file. e.g. I might want to have a date/time stamp version of a file so that I can reference both the original report and the backup version throughout a script:

$now = $(Get-Date -format "yyyy-MM-dd__HH-mm")
$ReportName = "MyReport-en.csv"
$Backups = "D:\Backups\Reports"

I found that using -join or + always inserted a space before the date/time stamp:

$ReportBackup = "$Backups\$($ReportName -split ".csv")" + "_$now.csv"
$ReportBackup = "$Backups\$($ReportName -split ".csv")" -join "_$now.csv"

I found a way to do this, but it looks feels inefficient with the triple $ and duplication of the .csv

$ReportBackup = "$Backups\$($($ReportName -split ".csv")[0])$_now.csv"

which results in:

$ReportBackup => D:\Backups\Reports\MyReport-en_2022-04-15__07-55.csv

Can you think of simpler/cleaner way to achieve the generic goal of inserting a piece of text before the extension, without the triple $ or duplication of the extension? ("Use a $name = "MyReport-en"" is not so useful because often I am reading a file object and get the name complete with extension.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

書生途 2025-01-28 13:54:28
$now = Get-Date -Format "yyyy-MM-dd__HH-mm"
$reportName = "MyReport-en.csv"
$backups = "D:\Backups\Reports"

$reportBackup = Join-Path $backups $reportName.Replace(".csv","_$now.csv")
$reportBackup

PS
如果您知道它是如何工作的,则使用.replace()没有风险。
此方法对情况很敏感,并取代所有发生。在这种特殊情况下,我们确切地知道名称,因此我们可以安全地使用此方法。

名称“ my.csvreport-en.csv”是一个胡说八道,但是如果问题明确提到通用解决方案“任何name.ext”:

$reportName = "My.aSd_Report-en.aSD"
$backups = "D:\Backups\Reports"

$reportBackup = Join-Path $backups ($reportName -replace "(?=\.[^.]+$)", (Get-Date -Format "_yyyy-MM-dd__HH-mm"))
$reportBackup
$now = Get-Date -Format "yyyy-MM-dd__HH-mm"
$reportName = "MyReport-en.csv"
$backups = "D:\Backups\Reports"

$reportBackup = Join-Path $backups $reportName.Replace(".csv","_$now.csv")
$reportBackup

P.S.
There is no risk in using .Replace(), if you know how it works.
This method is case sensitive and replaces all occurrences. In this particular case, we know exactly the name in advance, so we can use this method safely.

The name "My.csvReport-en.csv" is an nonsense, but if the problem explicitly referred to the universal solution "any-name.ext":

$reportName = "My.aSd_Report-en.aSD"
$backups = "D:\Backups\Reports"

$reportBackup = Join-Path $backups ($reportName -replace "(?=\.[^.]+$)", (Get-Date -Format "_yyyy-MM-dd__HH-mm"))
$reportBackup
撩发小公举 2025-01-28 13:54:28

如果您以FileInfo 对象获得了报告文件,则可以使用get-itemget-childitem,您会发现该对象具有方便您可以使用属性创建一个新的文件名,其中包含日期:

# assume $ReportName is a FileInfo object
$Backups = "D:\Backups\Reports"
# I'm creating a new filename using the '-f' Format operator
$NewName = '{0}_{1:yyyy-MM-dd__HH-mm}{2}' -f $ReportName.BaseName, (Get-Date), $ReportName.Extension
$ReportBackup = Join-Path -Path $Backups -ChildPath $NewName

如果但是$ reportName只是一个仅包含文件名的字符串,您可以执行:

$ReportName = "MyReport-en.csv"
$Backups    = "D:\Backups\Reports"
$baseName   = [System.IO.Path]::GetFileNameWithoutExtension($ReportName)
$extension  = [System.IO.Path]::GetExtension($ReportName)
$NewName    = '{0}_{1:yyyy-MM-dd__HH-mm}{2}' -f $baseName, (Get-Date), $extension
$ReportBackup = Join-Path -Path $Backups -ChildPath $NewName

PS仅使用始终风险。 。
另外,字符串.replace()方法工具敏感。

这意味着

'My.csvReport-en.csv'.Replace(".csv", "_$(Get-Date -Format 'yyyy-MM-dd__HH-mm').csv")

失败(返回MY_2022-04-15__13-36.CSVREPORT-EN_2022-04-15__13-36.CSV
并且

'MyReport-en.CSV'.Replace(".csv", "$(Get-Date -Format 'yyyy-MM-dd__HH-mm').csv")

根本不会替换任何东西,因为它找不到大写.csv
..

如果您真的想通过将扩展名替换为日期+扩展名来执行此操作,请选择更复杂的不敏感的REGEX -replace类似:

$ReportName -replace '^(.+)(\.[^.]+)

REGEX详细信息:

^              Assert position at the beginning of the string
(              Match the regular expression below and capture its match into backreference number 1
   .           Match any single character that is not a line break character
      +        Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)             
(              Match the regular expression below and capture its match into backreference number 2
   \.          Match the character “.” literally
   [^.]        Match any character that is NOT a “.”
      +        Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)             
$              Assert position at the end of the string (or before the line break at the end of the string, if any)
, "`$1_$(Get-Date -Format 'yyyy-MM-dd__HH-mm')`$2"

REGEX详细信息:

If you have obtained the report file as FileInfo object by perhaps using Get-Item or Get-ChildItem, you'll find that object has convenient properties you can use to create a new filename with the date included:

# assume $ReportName is a FileInfo object
$Backups = "D:\Backups\Reports"
# I'm creating a new filename using the '-f' Format operator
$NewName = '{0}_{1:yyyy-MM-dd__HH-mm}{2}' -f $ReportName.BaseName, (Get-Date), $ReportName.Extension
$ReportBackup = Join-Path -Path $Backups -ChildPath $NewName

If however $ReportName is just a string that only holds the filename, you can do:

$ReportName = "MyReport-en.csv"
$Backups    = "D:\Backups\Reports"
$baseName   = [System.IO.Path]::GetFileNameWithoutExtension($ReportName)
$extension  = [System.IO.Path]::GetExtension($ReportName)
$NewName    = '{0}_{1:yyyy-MM-dd__HH-mm}{2}' -f $baseName, (Get-Date), $extension
$ReportBackup = Join-Path -Path $Backups -ChildPath $NewName

P.S. It is always risky to simply use .Replace() on a filename because that doesn't allow you to anchor the substring to replace, which is needed, because that substring may very well also be part of the name itself.
Also, the string .Replace() method works case-sensitive.

This means that

'My.csvReport-en.csv'.Replace(".csv", "_$(Get-Date -Format 'yyyy-MM-dd__HH-mm').csv")

would fail (returns My_2022-04-15__13-36.csvReport-en_2022-04-15__13-36.csv)
and

'MyReport-en.CSV'.Replace(".csv", "$(Get-Date -Format 'yyyy-MM-dd__HH-mm').csv")

would simply not replace anything because it cannot find the uppercase .CSV
..

If you really want to do this by replacing the extension into a date+extension, go for a more complex case-insensitive regex -replace like:

$ReportName -replace '^(.+)(\.[^.]+)

Regex details:

^              Assert position at the beginning of the string
(              Match the regular expression below and capture its match into backreference number 1
   .           Match any single character that is not a line break character
      +        Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)             
(              Match the regular expression below and capture its match into backreference number 2
   \.          Match the character “.” literally
   [^.]        Match any character that is NOT a “.”
      +        Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)             
$              Assert position at the end of the string (or before the line break at the end of the string, if any)
, "`$1_$(Get-Date -Format 'yyyy-MM-dd__HH-mm')`$2"

Regex details:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文