Powershell 按修改日期查找特定文件并复制到相关文件夹

Powershell 按修改日期查找特定文件并复制到相关文件夹,powershell,Powershell,我正在寻找一个PowerShell脚本,它可以从源目录中找到文件N30008xx.txt、N30005xx.txt,并通过创建与文件修改日期同名的文件夹将它们复制到目标目录 我能够运行下面的脚本,该脚本根据文件修改日期创建文件夹 $p = "Filesourcepath" Get-ChildItem -Path $p | Where-Object { ! ($_.PSIsContainer) } | ForEach-Object { $newDir = Joi

我正在寻找一个PowerShell脚本,它可以从源目录中找到文件N30008xx.txt、N30005xx.txt,并通过创建与文件修改日期同名的文件夹将它们复制到目标目录

我能够运行下面的脚本,该脚本根据文件修改日期创建文件夹

$p = "Filesourcepath"

Get-ChildItem -Path $p |
    Where-Object { ! ($_.PSIsContainer) } | 
    ForEach-Object {
        $newDir = Join-Path $p ($_.LastWriteTime).ToString("yyyy-MM-dd")
        New-Item -Path $newDir -ItemType Directory -ErrorAction SilentlyContinue
        $_ | Move-Item -Destination $newDir
    }

下面是一个应该可以工作的PowerShell的修改版本

注意:目标目录不能位于源目录下,否则将进行永久递归移动

$p = pwd
$dst = "c:/tmp/testdir"

Get-ChildItem -Path $p | Where-Object  {
    $_.PSIsContainer -eq $false
} | ForEach-Object {
    $newdir = Join-Path -Path $dst -ChildPath ($_.LastWriteTime).ToString("yyyy-MM-dd")
    if (!(Test-Path -Path $newdir)) {
        Write-Host "Create directory $newdir"
        New-Item -Path $newdir -ItemType Directory
    }
    Write-Host "Copy file $_"
    Move-Item -Path $_ -Destination $newdir
}
您的代码原则上应该可以工作。 在撰写本文时,人们对复制和移动存在混淆,而且只匹配选择文件的方面也缺失了

下面是您的代码的简化版本,但它不能解释您的症状-您需要为我们提供更多信息来诊断您的问题

简化代码如下:

利用PSv3+-File Get-ChildItem参数限制与文件的匹配,而不是与目录的匹配-这节省了对Where对象{!$\u.PSIsContainer}的需要

使用-LiteralPath传递literal$dir路径;虽然作为位置默认值的-Path通常也可以正常工作,但需要注意的是,它将is参数解释为通配符表达式,这可能会产生意外的结果

使用-Filter提供文件掩码通配符表达式;这通常比使用-Path参数更可取,因为它在源Windows API调用处进行过滤,因此速度更快,这在处理大目录时会产生明显的差异。 警告:在-Filter参数中支持的通配符语言比PowerShell的更为有限,而且还存在一些遗留问题;简言之:坚持*和?应该很好;有关完整故事,请参阅

使用-Force而不是-ErrorAction SilentlyContinue来创建目录或使用先前存在的目录

请注意,New Item-ItemType Directory-Force在两种情况下都返回一个[System.IO.DirectoryInfo]实例,即新创建的目录或先前存在的目录,代码将利用该目录。 警告:重新概括此代码:

您正在源目录中创建目标子目录

如果要使用Get-ChildItem-Recurse以递归方式处理源目录,那么最终将处理两次匹配的文件:第一次是在移动它们时,第二次是在移动到的位置找到它们时。 然而,在这种特殊情况下,这只会导致效率低下,因为处理已经移动的文件会尝试将它们移动到已经存在的目录中,这是一个安静的禁止操作


它不会复制文件!虽然在枚举的目录中重新创建新文件的警告通常值得注意,但在这种情况下没有问题,因为没有使用-Recurse。小心使用Move Item-Path$\:遗憾的是,只有当$p恰好也是当前位置时,它才会起作用,因为$\实际上仅由文件名绑定;要么使用$\ FullName,要么使用管道-请参阅我的作为旁白:最好使用-LiteralPath。如果要复制某个内容,不应移动它。
# Create sample dir. with 2 sample files in it.
$tmpDir = New-Item -Force -Type Directory tmpDir
New-Item -Type File -Force -Path ('N30008xx.txt', 'N30005xx.txt' -replace '^', "$($tmpDir.FullName)/")

$dir = $tmpDir
$fileMask = 'N*.txt'

Get-ChildItem -File -LiteralPath $dir -Filter $fileMask | ForEach-Object {
  $newDir = Join-Path $dir $_.LastWriteTime.ToString("yyyy-MM-dd")
  $_ | Move-Item -Destination (New-Item -ItemType Directory -Force $newDir) 
}