【问题标题】:How can I use Powershell to keep two directories updated with the latest files如何使用 Powershell 使两个目录更新为最新文件
【发布时间】:2015-07-22 20:49:28
【问题描述】:

我有两个目录:

C:\G\admin\less
C:\G\user\less

在这些指令中,我有多个 less 和 css 文件。我知道所有文件的名称,所以我想将这些文件的列表硬编码到脚本中。也许这可能是一个数组或其他东西,但我对 PowerShell 的了解甚至不足以知道脚本语言中是否有数组。

C:\G\admin\less

html-light.less
html-light.css
html-dark.less
html-dark.css
do-not-track-me.less

C:\G\user\less

html-light.less
html-light.css
html-dark.less
html-dairk.css
do-not-track-me.less

有没有一种方法可以使用 PowerShell 逐个检查这些文件(我想在我的程序中硬编码)并将最后修改的文件从其目录复制到另一个目录,以便两个目录都包含这些文件的最新版本是否相同?

请注意,我需要一一评估预定义的文件列表。将一个目录中的修改日期与另一个目录中的修改日期进行比较,并根据需要进行复制。

【问题讨论】:

  • 我以为你只是说他们不会改变
  • @MathiasR.Jessen 我认为她的意思是文件名称不会改变。
  • 无需重新发明轮子。只需使用robocopy
  • 那么哪个目录有较新的文件?
  • 任何一个目录都可以有较新的文件。根据我的需要,我在两个目录中都说了 20 个已知文件。我可以将这 20 个硬编码到一个 powershell 脚本中。我需要的是一个脚本,它可以检查目录 a 和目录 b 中的每个文件,如果一个文件的修改日期大于另一个文件,我需要将该文件复制到另一个目录。

标签: powershell powershell-2.0


【解决方案1】:

再次假设这不是最好的解决方案或方法
此解决方案假定以下
- 当一个文件夹上的 LastWriteTime 大于另一个时,它会将其复制到另一个文件夹。
- 由于懒惰,我没有进行路径验证,但如果您想要进行路径验证,请询问。
- 我假设必须跟踪这些文件夹中的所有文件,否则请阅读代码注释。 - 我建议你在运行脚本之前备份你的文件夹。

#if there is a file you don't want to track on those folder (for example you don't want to track txt files) 
#just  write $userFiles=dir C:\G\user\less\ -Exclude "*.txt"
#if you don't want track txt but only one of them should be track among with other file format
#$userFiles=dir C:\G\user\less\ -Exclude "*.txt" -Include "C:\G\user\less\Txtadditionaltotrack.txt"
$userFiles=dir C:\G\user\less\
$adminfiles=dir C:\G\admin\less\
foreach($userfile in $userFiles)
{
   $exactadminfile= $adminfiles | ? {$_.Name -eq $userfile.Name} |Select -First 1
   #my suggestion is to validate if it got the file.
   #By now because of my lazy i will not call the test-path to validate if it got the file
   #I'm assuming all directory are exact copy of each other so it will find the file.

  if($exactadminfile.LastWriteTime -gt $userfile.LastWriteTime)
  {
    Write-Verbose "Copying  $exactadminfile.FullName to $userfile.FullName "
    Copy-Item -Path $exactadminfile.FullName -Destination $userfile.FullName -Force
  }
  else
  {
    Write-Verbose "Copying  $userfile.FullName to $exactadminfile.FullName "
    Copy-Item -Path $userfile.FullName -Destination $exactadminfile.FullName -Force
  }
}

你可以改进它,因为这段代码总是将文件从一个目录复制到另一个目录中,你可以验证,这样当两个的 lastwriteTime 相等时,它就不会复制。 您可以通过多种方式对其进行改进。我希望你有这个想法

找到对代码所做的修改,以便它可以满足此要求。
请阅读代码中的评论。
请注意,我没有遵循最佳实践(避免意外错误,正确命名所有变量,...)

#to make it more dynamical you can save on one file
#all the file names including extension in different lines.
#For example on path C:\FilesToWatch\watcher.txt
#$filestowatch=get-content C:\FilesToWatch\watcher.txt

$filestowatch="felicio.txt","marcos.txt"
$userFiles=dir C:\G\user\less\
$adminfiles=dir C:\G\admin\less\

#Optionally instead of use this if approach you can 

#$userFiles=dir C:\G\user\less\ |? {$filestowatch -contains $_.Name}
#$adminfiles=dir C:\G\admin\less\|? {$filestowatch -contains $_.Name}

#loading in the above manner the first if statement on code bellow can be removed because 
#We make sure that $userFiles and $adminfiles only have correct file to monitor

foreach($userfile in $userFiles)
{
   if($filestowatch -contains $userfile.Name)
   {
      $exactadminfile= $adminfiles | ? {$_.Name -eq $userfile.Name} |Select -First 1
       #my suggestion is to validate if it got the file.
       #By now because of my lazy i will not call the test-path to validate if it got the file
       #I'm assuming all directory are exact copy of each other so it will find the file.

      if($exactadminfile.LastWriteTime -gt $userfile.LastWriteTime)
      {
         Write-Verbose "Copying  $exactadminfile.FullName to $userfile.FullName "
         Copy-Item -Path $exactadminfile.FullName -Destination $userfile.FullName -Force
       }
       else
       {
          Write-Verbose "Copying  $userfile.FullName to $exactadminfile.FullName "
          Copy-Item -Path $userfile.FullName -Destination $exactadminfile.FullName -Force
       }
    }
}

【讨论】:

  • 你好,费利西奥。我在目录中有一些我想要执行此操作的文件,而其他文件则不是。我可以以某种方式列出文件并将它们放入 powershell 代码中。所以它不会执行 foreach 并选择所有文件?
  • 是的,您可以有很多方法可以做到其中一种方法是在代码注释中 $userFiles=dir C:\G\user\less\ -Exclude "*.txt" -Include "C :\G\user\less\Txtadditionaltotrack.txt" 您可以在包含参数中添加由逗号分隔的所有文件,也可以使用 where 子句通过管道传输 dir 命令。你知道怎么做吗??
  • @SamanthaJ 你能检查一下新方法吗?然后给出反馈
  • 谢谢费利西奥。我会在接下来的 24 小时内进行检查,然后通知您。我认为它看起来正是我所需要的。如果我想运行它,我是否将它放在以 .ps1 结尾的文件中?
  • 是的,使用 .ps1 扩展名保存。假设您想通过双击运行,创建一个批处理文件打开记事本并粘贴以下不带引号的代码。 “powershell -NoProfile -ExecutionPolicy Bypass .\yourfile.ps1”并使用 bat 扩展名保存。然后只需双击。首先,我建议您复制并粘贴到 powershell 控制台中,以查看它是否正常工作。如果没关系。您可以按照此 cmets 上的过程确保您的 bat 文件和 ps1 文件在同一目录中。
【解决方案2】:

我认为您需要的是符号链接,也就是符号链接。

使用符号链接,您可以定义始终同步的文件和文件夹,其中目标文件会在修改原始文件时自动更新。

要创建符号链接,请在控制台/命令提示符中输入以下内容:

mklink /[command] [link path] [file or folder path]

Mklink 可以根据这些命令创建多种类型的链接:

  • /D – 创建软符号链接,类似于 Windows 中的标准文件夹或文件快捷方式。这是默认选项,如果您不输入命令,mklink 将使用它。
  • /H – 创建文件的硬链接。
  • /J – 创建文件夹的硬链接。

语法很简单。选择您的选项,定义符号链接所需的路径,最后定义原始文件/文件夹的路径。

例如,假设我正在开发一个新项目,我想通过 Dropbox 共享文件夹将它分享给我的客户。我不想将我的所有工作区都移动到 Dropbox,我只想将那个特定的文件夹分享给他们:

mklink /J C:\Dropbox\clients_shared_folders\project_x C:\my_dev_rootfolder\project_x

注意,第一个路径是我要创建的符号文件夹,而第二个路径是现有目录。

在您的情况下,我将假设您在 admin 文件夹上工作,并希望在 user 文件夹上生成同步副本:

mklink /J C:\G\user\less C:\G\admin\less

这是一篇不错的文章,可了解更多信息: http://www.howtogeek.com/howto/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/

【讨论】:

  • 创建符号链接意味着您只有一组文件。您没有从主服务器同步用户文件夹。对用户文件夹的任何更改都会直接影响主文件夹。
  • 感谢您的建议,但是我确实需要一个可以运行的脚本,因为在开发过程中我可能无法处理一个文件,然后想将其推送到另一个文件夹。
  • 符号链接只需要定义一次。在您删除符号链接之前,它们将保持活动状态。但我明白你的意思——你不想在保存时破坏主代码。
猜你喜欢
  • 1970-01-01
  • 2016-06-22
  • 2016-09-29
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
相关资源
最近更新 更多