从 CSV/TXT 创建文件夹并将匹配列移动到 Powershell 或 Batch 中的新目录

Posted

技术标签:

【中文标题】从 CSV/TXT 创建文件夹并将匹配列移动到 Powershell 或 Batch 中的新目录【英文标题】:Create folders from CSV/TXT and move matching column into new directory in Powershell or Batch 【发布时间】:2020-12-22 05:12:27 【问题描述】:

我有一个包含大约 8000 行格式的 CSV(或 XLSX 或 TAB - 我可以导出到多个)文件:

|   17854   |   SMITH   |   14785236   |
|   58487   |   JONES   |   96325874   |
|   65715   |   SMITH   |   84682254   | <-- unique via col3
|   65822   |   SMITH   |   14785236   | <-- same as col 2 + 3

第 2 列和第 3 列中的一些数据是相同的,而第 1 列始终是唯一的 (ID)。

在目标目录中,我有以下结构:

- 17854
- ...
- 58487
- ...
- 65715
- ...
- 65822

基本上(几乎)第 1 列中列出的每个 ID 都有一个文件夹。

我希望能够从第 2 + 3 列的格式创建一个文件夹:

- JONES 96325874
- SMITH 14785236
- SMITH 84682254

然后将第 1 列中匹配的文件夹移动到相应的新目录中:

- JONES 96325874
---- 58487
- SMITH 14785236
---- 17854
---- 65822
- SMITH 84682254
---- 65715

我可以通过编辑文件和删除 ID 列来创建文件夹:

Set-Location "A:\" 
$Folders = Import-Csv c:\listOfItems.csv
ForEach ($Folder in $Folders)  
    New-Item $Folder.Name  + $Folder.Number -type directory 
 

或最初在批处理文件中:

for /F "usebackq delims=" %%i in (listOfItems.txt) do md "%%i" 

有什么方法可以将匹配第一列名称的移动部分移动到第 2 + 3 列的组合中?

我不太熟悉 Powershell,但我觉得它比批处理脚本更有针对性?这将是我每个月都必须运行的东西,并且手动执行它已经......很难。

【问题讨论】:

为什么要删除 ID 列?如果 csv 文件的格式正确,我看不出你为什么需要删除它的原因,特别是考虑到它会让我认为你想要完成的事情变得更容易...... @WilliamHiggs 抱歉,我在批处理文件中删除了它,txt 文件只是从文件中的行创建名称。从 CSV 文件复制到文本文件中 好吧,如果您使用的是 powershell,则不需要这样做。当您将 csv 导入到 powershell 中时,该变量就会变成一个对象数组,这些对象的属性就是 csv 中的不同“列”。你似乎已经做了很多工作。我会发布我认为您正在寻找的答案。 抱歉@WilliamHiggs - 大部分时间已经输入了我的答案 【参考方案1】:

不要卖空自己!!根据你所说的,以及我认为你想做的,你已经完成了大部分工作。如果我没看错您的问题,那么您现在只需将“id”文件夹移动到您创建的包含“name”和“number”属性的文件夹中即可。如果是这种情况,并且假设您已导入到 powershell 的这个 csv 包含所有三列,您可以这样做

$Folders = Import-Csv c:\listOfItems.csv
ForEach ($Folder in $Folders)  
    New-Item "C:\path\to\createfolder\$($folder.name)`$($Folder.Number)" -type directory 
    Move-Item -Path "C:\path\to\id\folder\$($folder.id)" -Destination "C:\path\to\createfolder\$($folder.name)`$($Folder.Number)\"
 

【讨论】:

【参考方案2】:

通过使用 $Folder.ID 属性(如果您将其保留在 CSV 文件中),以下内容应该可以满足您的要求:

ForEach ($Folder in $Folders)  
    $base = New-Item ($Folder.Name  +" "+ $Folder.Number) -type directory -Force
    Move-Item $Folder.ID $base.FullName
 

-Force 已被添加,因为如果您重新运行它,您需要命令来重新创建目录,否则$base 将不会保存值。如果你想聪明一点,你可以先检查目录是否存在,然后再决定是否创建它。

我还想展示一种在获取全部 8000 条记录之前尝试的测试方法:

ForEach ($Folder in $Folders[0..5])  
    $base = New-Item ($Folder.Name  +" "+ $Folder.Number) -type directory -Force
    Move-Item $Folder.ID $base.FullName -WhatIf

通过将[0..5] 添加到$Folders,PowerShell 将仅对 CSV 文件中的前 6 个(0、1、2、3、4、5)项执行文件夹创建操作。添加到 Move-Item CmdLet 的 -WhatIf 开关仅显示 PowerShell 将执行的操作,因此您可以在关闭 -WhatIf 选项之前先进行验证:

What if: Performing the operation "Move Directory" on target 
"Item: C:\temp\17854 Destination: C:\temp\SMITH 14785236\17854".

【讨论】:

以上是关于从 CSV/TXT 创建文件夹并将匹配列移动到 Powershell 或 Batch 中的新目录的主要内容,如果未能解决你的问题,请参考以下文章

Awk多模式匹配,并将输入文件的输出格式化为列。

如何用批处理命令把1个文件夹里多个csv文件的某一列合并成一个txt

插入行并将数据从水平布局移动/拉到垂直布局

根据查找值将值从一张表匹配并粘贴到另一张表中

如何匹配两个不同表中的列并将选定的列输出到 MySQL 中的第三个表?

两个文件中的AWK列匹配,打印不同的列