Хорошо, я отвечу на ваши вопросы в вашем комментарии. Импорт данных в 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» в нем) , сделайте это ключом, а затем сделайте всю запись значением. Так, до сих пор мы имеем это:
#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"
}
}
Edit: Хорошо, давайте сломаем процесс переименования здесь. Здесь много труб, поэтому я постараюсь сделать это шаг за шагом. Во-первых, у нас есть 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
заявлении и улавливает 2 вещи. Первое, что он захватывает, - это все в начале имени перед запятой. Затем он пропускает все, пока не получит последний фрагмент текста в конце имени и не захватит все после последнего пробела. Новый пробой на RegEx101: https://regex101.com/r/zW8sW1/2
Итак, вы хотите, чтобы ID_LName, которое можно получить из имени папки, действительно не нужно даже использовать ваш CSV-файл на данный момент, я не думаю. Мы создаем новое имя файлов, основанное на автоматической переменной $Matches
, используя вторую группу захвата и первую группу захвата и помещая знак подчеркивания между ними. Затем мы просто перебираем файлы с помощью цикла For
, основываясь на том, сколько файлов было найдено. Итак, мы начинаем с первого файла в массиве $Files
(запись 0), добавляем это к $NewName
с подчеркиванием и используем его для переименования файла.
Будут ли имена папок всегда в этом формате? 'LastName, FirstName ID #', если это так должно быть достаточно просто. Я лично использовал [этот скрипт] (https://gallery.technet.microsoft.com/office/17bcabe7-322a-43d3-9a27-f3f96618c74b) из галереи MS Script, чтобы импортировать данные в PowerShell, но для упрощения ссылок. – TheMadTechnician
Да все имена папок находятся в этом формате. Есть ли причина импортировать файл в PowerShell? Преимущество? Как я могу использовать эти импортированные данные для переименования файлов? –