如何通过gci脚本的node_modules防止递归

时间:2019-05-13 21:20:54

标签: visual-studio powershell

我发现了这个很棒的powershell脚本

gci -include bin,obj -recurse | remove-item -force -recurse

Chris Jthis answer的评论

我每天多次使用它。

如何防止它通过任何node_modules文件夹(如果存在)或其子级运行?

我尝试过

的各种版本
gci -exclude node_modules -include bin,obj -recurse | remove-item -force -recurse

没有成功。

更新: 阅读@ HAL9256的翔实答案后,我意识到我未能包括一项重要要求。我在git repo的根目录下运行此脚本。因此,它将遍历多个C#项目文件夹,从而删除所有文件夹的bin和obj文件夹。这仅是必需的,因为Visual Studio 2017和2019解决方案清理不会删除所有内容,并且由于我们正在从框架转换为标准/核心的过程中,因此清理后会在bin和/或obj文件夹中留下一些工件,从而导致问题通过git分支更改在转换给定项目(可能从内核回框架)时中断。

2 个答案:

答案 0 :(得分:0)

此问题的根源是滥用递归与过滤相结合。我将通过一些示例进行说明。首先,我们应该建立一个示例目录结构:

mkdir Temp
mkdir Temp\bin
mkdir Temp\obj
mkdir Temp\node_modules
mkdir Temp\node_modules\bin
mkdir Temp\node_modules\obj

Out-File .\Temp\Readme.md
Out-File .\Temp\bin\Readme.md
Out-File .\Temp\obj\Readme.md
Out-File .\Temp\node_modules\Readme.md
Out-File .\Temp\node_modules\bin\Readme.md
Out-File .\Temp\node_modules\obj\Readme.md

cd .\Temp\

让我们尝试一些示例。我将把Get-ChildItem的内容传送到Select-Object中,以更好地说明我们要检索的内容。首先,香草Get-ChildItem

PS C:\Temp> Get-ChildItem | Select-Object FullName

FullName
--------
C:\Temp\bin
C:\Temp\node_modules
C:\Temp\obj
C:\Temp\Readme.md

这将返回我们期望的值,相当于dir。现在,让我们尝试-Include仅“包含” bin文件夹。

PS C:\Temp> Get-ChildItem -Include bin | Select-Object FullName
PS C:\Temp>

嗯。它什么也没返回。。。我们以为它将得到所有内容的列表,并且“仅”包括bin文件夹。相反,它所做的是将命令解释为“无”的Get-ChildItem,(因为我们未指定要获取的任何文件),将“无”的“ Include”解释为模式{{1} }。这很有意义,并在Docs中列出了“包含需要Path参数”。好。让我们对其进行更改,以使所有内容bin 然后执行*然后,我们应该得到想要的...对吗?

-Include bin

Hu?我以为通配符会包含PS C:\Temp> Get-ChildItem * -Include bin | Select-Object FullName PS C:\Temp> 文件夹,对吗?那不是它的工作原理吗?让我们将其更改为bin文件而不是目录:

-Include

所以看起来像是显式过滤,带通配符的是文件,而不是目录。那么,其中包含目录的原始示例如何工作?...这是因为PS C:\Temp> Get-ChildItem * -Include Readme.md | Select-Object FullName FullName -------- C:\Temp\Readme.md 的工作原理不同。 -Recurse改变了我们得到的东西,它返回了一切,因此-Recurse可以工作:

Include

在此示例中,当我们不必指定通配符PS C:\Temp> Get-ChildItem -Include bin -Recurse | Select-Object FullName FullName -------- C:\Temp\bin C:\Temp\node_modules\bin 过滤器时,*隐式地从目录中获取所有内容。注意:它包含与名称-Recurse匹配的目录。另外,请注意,它不包含目录内的文件。

为什么示例1:

bin

之所以可行,是因为gci -include bin,obj -recurse | remove-item -force -recurse 返回目录,而Get-ChildItemRemove-Item-Force则负责删除文件。

要证明没有什么时髦的事,让我们做一个-Recurse

-Exclude node_modules

好吧……回报率超出了预期……但没有。请注意,它没有返回PS C:\Temp> Get-ChildItem -Exclude node_modules -Recurse | Select-Object FullName FullName -------- C:\Temp\bin C:\Temp\bin\Readme.md C:\Temp\node_modules\bin C:\Temp\node_modules\bin\Readme.md C:\Temp\node_modules\obj C:\Temp\node_modules\obj\Readme.md C:\Temp\node_modules\Readme.md C:\Temp\obj C:\Temp\obj\Readme.md C:\Temp\Readme.md 。这是因为C:\Temp\node_modules是正确的。它排除了专门命名为-Exclude node_modules的文件夹,并包括了其他所有内容。

是第二个示例不起作用的原因:

node_modules

排除过滤器将排除名为gci -exclude node_modules -include bin,obj -recurse | remove-item -force -recurse 的特定文件夹,但是由于node_modules-Recurse匹配-Includebin的所有子文件夹。当然,obj中的哪个 吨很多,因此无法按我们的意愿工作。

因此,如果node_modules不适用于目录,并且-Include太深,那么什么将解决@cResults问题?好吧,为什么不摆弄过滤器,我们为什么不只是简单地索要我们想要的文件夹呢?

-Recurse

这没关系,它返回了文件夹的内容,就像前面的示例一样,子项而不是目录...好吧,我们确实想要的是文件夹项,因此我们使用PS C:\Temp> Get-ChildItem bin,obj | Select-Object FullName FullName -------- C:\Temp\bin\Readme.md C:\Temp\obj\Readme.md 代替Get-ChildItem

Get-Item

现在,切换到PS C:\Temp> Get-Item bin,obj | Select-Object FullName FullName -------- C:\Temp\bin C:\Temp\obj ,我们得到的是文件夹,而不是文件夹中的子项,我们现在可以将其与Get-Item一起使用,剩下的工作就可以了:

Remove-Item

答案 1 :(得分:0)

对于任何正在寻找的人,就像我刚才一样,这里有一个完整的解决方案。 使用 Lee_Dailey 建议的 Where-Object,您可以在递归后排除 node_modules 目录。

gci -include bin,obj -recurse | where-object {$_.FullName -notlike '*\node_modules*'} | remove-item -force -recurse