【问题标题】:Powershell Remove-Item IF file already exists after Copy-itemPowershell Remove-Item IF 文件在 Copy-item 后已存在
【发布时间】:2014-06-06 02:51:57
【问题描述】:

我需要在我的脚本中添加一个安全网。我正在尝试根据通过 txt 文件提供的用户列表进行复制工作。将文件从该用户主目录复制到新位置。复制文件后,检查文件是否存在于新位置。如果是,则删除项目。

有人可以帮助我吗?我只是不知道如何实现“如果文件存在”逻辑。

$username = Get-Content '.\users.txt'
foreach ($un in $username)
{
  $dest = "\\server\homedirs\$un\redirectedfolders"
  $source = "\\server\homedirs\$un"
  New-Item -ItemType Directory -Path $dest\documents, $dest\desktop

  Get-ChildItem $source\documents -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\documents
  Get-ChildItem $source\desktop -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\desktop

  Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | Remove-Item -Recurse
}

【问题讨论】:

    标签: powershell


    【解决方案1】:

    Test-Path commandlet 将帮助您检查文件是否存在

    http://technet.microsoft.com/en-us/library/ee177015.aspx

    【讨论】:

      【解决方案2】:

      要回答您的问题本身,您可以这样做:

      Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | %{
        if (Test-Path ($_. -replace "^$([regex]::escape($source))","$dest")) {
          Remove-Item $_ -Recurse
        }
      }
      
      • Test-Path 如果给定路径的文件存在则返回 $true,否则返回 $false
      • $_ -replace "^$([regex]::escape($source))","$dest" 通过将路径开头的 $source 替换为 $dest,将您枚举的每个源项的路径转换为相应的目标路径。李>
      • -replace 运算符的第一个参数的基本正则表达式是 ^$source(这意味着“匹配字符串开头的 $source 的值” )。但是,您需要使用 [regex]::escape 以防 $source 包含任何正则表达式特殊字符,实际上 极有可能 Windows 路径,因为它们包含反斜杠。例如,您在此处为 $source 提供的值包含\s,在正则表达式中表示“任何空白字符”。 $([regex]::escape($source)) 将使用正确转义的任何正则表达式特殊字符插入 $source 的值,以便您匹配显式值。

      也就是说,如果您的目的是将每个项目复制到一个新位置,并且只有在复制到新位置成功时才移除原件,那么您似乎是在重新发明轮子。为什么不直接使用 Move-Item 而不是 Copy-Item


      与问题没有直接关系,但不是对每个子目录重复相同的命令,您可以使用 foreach 循环:

      foreach ($subdir in (echo documents desktop)) {
        # Whatever command you end up using to copy or move the items, 
        # using "$source\$subdir" and "$dest\$subdir" as the paths
      }
      

      【讨论】:

        【解决方案3】:

        如果文件不存在,删除文件的最短方法是不使用Test-Path,但是:

        rm my_file.zip -ea ig

        这是一个简短的版本

        rm my_file.zip -ErrorAction Ignore

        这样更易读,更干

        if (Test-Path my_file.zip) { rm my_file.zip }

        【讨论】:

        • 这不仅更具可读性,而且更正确。首先测试存在的模式是错误的,因为当Test-Path 返回肯定答案时,该文件夹可能已经被删除,此时调用香草Remove-Item 将引发错误。
        • 我什至没有意识到这一点,你完全正确。另一个好处是它还清楚地说明了程序员的意图——如果我想删除,之前测试一些东西是一种噪音。
        • 再想一想,这里的问题是它可能隐藏了一个不同的错误。例如,该文件可能存在,但权限问题阻止您删除它。我不是 PS 专家,但可以快速搜索 ErrorVariable,这可能有助于消除此类情况的歧义。
        • ErrorVariable 或使用-ea 0(静默继续但记录错误),然后检查错误。
        • 必须检查 ErrorVariable 违背了使其比使用 Test-Path 更短的目的。我喜欢这样做:Get-ChildItem * -Include my_file.zip | Remove-Item。它让我不必指定两次文件名
        【解决方案4】:

        @Adi Inbar,我需要使用这样的功能,因为我需要将文件移动到远程会话,当我尝试 -ToSession 时,Move-Item 不起作用......只有 Copy-Item。 关键是如果电源或互联网出现故障,脚本将删除文件,即使它没有被复制。

        $username = "name"
        $password = ConvertTo-SecureString "password" -AsPlainText -Force
        $credential = New-Object System.Management.Automation.PSCredential -ArgumentList ($username, $password)
        $Session = New-PSSession -ComputerName "IPAdress" -Credential $credential 
        Copy-Item -Path C:\userPC_1\csv-output\*.csv  -Destination C:\userPC_2\Documents\Test_Scripts -ToSession $Session -Verbose
        Get-PSSession | Remove-PSSession
        Get-ChildItem -Path C:\userPC_1\csv-output\*.csv | Remove-Item -Force
        

        【讨论】:

          猜你喜欢
          • 2012-07-18
          • 2021-11-09
          • 2016-11-07
          • 2017-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多