2015-06-24 60 views
1

任何人都有關於如何通過查找與索引文件的關聯來重命名文件的想法?使用索引重命名文件(Excel)

我有類似下面的文件/文件夾結構: 文件夾名稱=「李四,約翰EO11-123」這個文件夾

索引文件(MS Excel中)下 幾個文件有幾個專欄。它包含2列(First和Last)中的名稱。它還有一個包含號碼EO11-123的列。

我想要做的是編寫一個腳本來查看目錄中的文件夾名稱,比較/查找索引文件中的關聯值(如EO11-123),然後重命名下的所有文件在索引中使用第四列值的文件夾。

所以,

文件夾名=「李四,約翰EO11-123」,指數COLUMN1包含相同的值「EO11-123」,用COLUMN2值「111111_000000」並重命名所有文件目錄文件夾下的「 111111_000000_0「,」111111_000000_1「,」111111_000000_2「等。

這可能與PowerShell或VBScript?

+0

文件夾名稱是否始終採用該格式? '姓氏,名字ID#',如果是的話,這應該很簡單。我個人使用MS腳本庫中的[此腳本](https://gallery.technet.microsoft.com/office/17bcabe7-322a-43d3-9a27-f3f96618c74b)將數據導入到PowerShell中,以便於參考。 – TheMadTechnician

+0

是的文件夾名稱都是這種格式。有沒有理由將文件導入PowerShell?優點?我將如何去使用導入的數據來重命名文件? –

回答

0

好的,我會在你的評論中首先回答你的問題。將數據導入PowerShell允許您在PowerShell中創建一個您可以匹配的數組,或者更好地創建一個HashTable來引用您的重命名目的。稍後我會介紹它,但它比嘗試讓PowerShell與Excel交談並使用Excel的搜索功能要好得多,因爲這種方式全部在PowerShell中,並且沒有第三方應用程序依賴關係。至於導入,該腳本是一個可以加載到當前會話中的函數,因此您可以運行該函數並自動處理導入(它會打開Excel,然後打開XLS(x)文件並將其保存作爲臨時CSV文件,關閉Excel,將該CSV文件導入PowerShell,然後刪除臨時文件)。現在

,你不說出你的XLS文件的樣子,所以我會假設它有一個標題行,看起來是這樣的:

FirstName | Last Name | Identifier | FileCode 
Joe   | Shmoe  | XA22-573  | JS573 
John  | Doe   | EO11-123  | JD123 

如果這不是你的格式,你我需要修改我的代碼或者你的文件,或者兩者兼而有之。

那麼,我們該怎麼做呢?首先,下載,保存,如果需要,取消屏蔽腳本到Import-XLS。然後我們將該源文件加載到當前的PowerShell會話中。一旦我們有了函數,我們將運行它並將結果賦值給一個變量。然後,我們可以創建一個空的散列表,並且對於導入數組中的每個記錄,在散列表中創建一個條目,其中的'標識符'屬性(在您的示例中,上面的示例中值爲「EO11-123」) ,使該Key,然後使整個記錄的價值。所以,到目前爲止,我們有這樣的:

#Load function into current session 
. C:\Path\To\Import-XLS.ps1 

$RefArray = Import-XLS C:\Path\To\file.xls 
$RefHash = @{} 

$RefArray | ForEach($RefHash.Add($_.Identifier, $_)} 

現在,你應該能夠引用該標識符來訪問任何屬性的相關記錄,如:

PS C:\> $RefHash['EO11-123'].FileCode 

JD123 

現在,我們只需要從該文件夾中提取該名稱,並重命名其中的所有文件。從這裏挺直的。

Get-ChildItem c:\Path\to\Folders -directory | Where{$_.Name -match "(?<=)(\S+)$"}| 
    ForEach{ 
     $Files = Get-ChildItem $_.FullName 
     $NewName = $RefHash['$($Matches[1])'].FileCode 
     For($i = 1;$i -lt $files.count;$i++){ 
      $Files[$i] | Rename-Item -New "$NewName_$i" 
     } 
    } 

編輯:好,讓我們在這裏打破重命名過程。這裏有很多管道系統,所以我會嘗試一步一步來。首先,我們有Get-ChildItem,它爲您指定的路徑獲取文件夾列表。這部分足夠簡單。然後它將管道傳送到Where語句,該語句過濾結果以檢查每個人的姓名,以查看它是否與正則表達式「(?< =)(\ S +)$」匹配。如果你不熟悉正則表達式的工作方式,你可以在https://regex101.com/r/zW8sW1/1處看到相當好的細分。所做的是匹配名稱中包含多個「單詞」的所有文件夾,並捕獲最後一個「單詞」。它將其保存在自動變量$Matches中,並且由於它捕獲了文本,該文本被分配到$Matches[1]。現在代碼在這裏出現故障,因爲您的CSV未按照我的設想進行佈局,並且您希望命名爲不同的文件。我們將不得不在飛行中做一些調整。

因此,那些通過過濾器文件夾將得到管道輸送到一個ForEach循環(我曾在以前是一個錯字,有一個(代替{,現在這是固定的)。因此,對於每個文件夾,首先獲取該文件夾中的文件列表並將它們分配給變量$Files。它還設置了$NewName變量,但由於您的CSV中沒有列名爲「FileCode」的行,因此該行對您無效。它使用前面提到的$Matches自動變量來引用我們用所有標識符代碼設置的散列表,然後查看該特定記錄的屬性以設置要分配給文件的新名稱。既然你想要的和我想象的是不同的,而你的CSV有不同的屬性,我們將重新編制前面的Where聲明和這一行。下面是腳本的該位現在閱讀:

Get-ChildItem c:\Path\to\Folders -directory | Where{$_.Name -match "^(.+?), .*? (\S+)$"}| 
    ForEach{ 
     $Files = Get-ChildItem $_.FullName 
     $NewName = $Matches[2] + "_" + $Matches[1] 

那現在在Where聲明相匹配的文件夾名稱,拍攝兩件事情。它的第一件事是在逗號前的名字開頭的所有東西。然後它跳過所有內容,直到獲得名稱末尾的最後一段文本,並捕獲最後一個空格後的所有內容。 RegEx101的新分類:https://regex101.com/r/zW8sW1/2

所以你想要ID_LName,它可以從文件夾名稱中獲得,這裏我甚至不需要甚至使用你的CSV文件。我們使用第二個捕獲組和第一個捕獲組並在它們之間放置下劃線,基於自動$Matches變量創建文件的新名稱。然後,我們通過使用For循環遍歷文件來查找找到了多少個文件。因此,我們從數組$Files(記錄0)中的第一個文件開始,將其添加到帶有下劃線的$NewName,並使用該文件重命名該文件。

+0

你可以分解最後一部分。解釋腳本的重命名部分中的所有內容?我想更好地理解這一點。我將嘗試修改你的代碼,因爲我只有3列。 FNAME,LNAME,標識符。我看不到NewName最終會成爲什麼樣的人。我將重命名爲:「LNAME_IAD」 –

+0

得到散列數字。現在我只需要回答上面question1的重命名操作。它使用標識符查找我的文件夾並將其重命名爲下面的文件。問題是它沒有將它們重命名爲「Identifier_LastName.pdf」 –

+0

對不起,今天晚些時候開始工作,所以直到現在我還沒有機會真正看到它。讓我編輯我的答案,看看我能否更好地解釋重命名部分。 – TheMadTechnician