Копировать имена файлов из одной папки в другую, сохраняя оригинальные расширения

Мне нужна помощь с копированием имен файлов (не самих файлов) с диска C на диск D. Мне удалось найти следующий код powershell в Интернете:

$names = @()
$getPath = "C:\MyFiles"
$setPath = "D:\MyFiles"
Get-ChildItem $getPath |
    Foreach-object{
    $names += $_
}
$i = 0
Get-ChildItem $setPath |
Foreach-object{
    Rename-Item -Path $_.FullName -NewName $names[$i]
    $i++
}

Этот код успешно переименовывает / копирует все имена файлов из C:\MyFiles в D:\MyFilesстрого по соответствующим позициям (показатели в перечислении).

Тем не менее, он также обновляет расширения, например:

C:\MyFiles\myfile.txt переименовывает D:\MyFiles\thisfile.docx в D:\MyFiles\myfile.txt

Есть ли способ отредактировать код Powershell, чтобы переименовать только базу имени файла (например, myFile) при сохранении расширений целевых файлов (например, .docx)?

Чтобы C:\MyFiles\myfile.txt переименовывает D:\MyFiles\thisfile.docx в D:\MyFiles\myfile.docx, с использованием

1 ответ

Решение

Звучит так, как будто вы хотите переименовать файлы в целевом каталоге по месту, основываясь на соответствующих файлах в исходном каталоге - при сохранении расширений файлов целевого каталога:

$getPath = "C:\MyFiles"
$setPath = "D:\MyFiles"
$sourceFiles = Get-ChildItem -File $getPath

$iRef = [ref] 0
Get-ChildItem -File $setPath | 
  Rename-Item -NewName { $sourceFiles[$iRef.Value++].BaseName + $_.Extension }
  • Для предварительного просмотра полученных имен файлов добавьте -WhatIf к Rename-Item вызов.

  • .BaseName собственность [System.IO.FileInfo] объекты выводятся Get-ChildItem возвращает часть имени файла без расширения.

  • $_.Extension извлекает существующее расширение входного файла (т. е. целевого файла), включая ведущие .

  • Обратите внимание, что блок скрипта ({ ... }) перешел к Rename-Item создает дочернюю переменную области видимости, поэтому вы не можете увеличивать переменную непосредственно в области действия вызывающей стороны (при этом каждый раз будет создаваться новая копия такой переменной с исходным значением); следовательно, [ref] экземпляр создается для косвенного хранения номера, который дочерняя область может затем изменить с помощью .Value имущество.


Вот полный пример:

Примечание. Хотя в этом примере используются похожие имена файлов и одинаковые расширения, код работает в общем, с любыми именами и расширениями.

# Determine the temporary paths.
$getPath = Join-Path ([System.IO.Path]::GetTempPath()) ('Get' + $PID)
$setPath = Join-Path ([System.IO.Path]::GetTempPath())  ('Set' + $PID)

# Create the temp. directories.
$null = New-Item -ItemType Directory -Force $getPath, $setPath

# Fill the directories with files.

# Source files: "s-file{n}.source-ext"
"--- Source files:"
1..3 | % { New-Item -ItemType File (Join-Path $getPath ('s-file{0}.source-ext' -f $_)) } | 
  Select -Expand Name

# Target files: "t-file{n}.target-ext"
"
---- Target files:"
1..3 | % { New-Item -ItemType File (Join-Path $setPath ('t-file{0}.target-ext' -f $_)) } | 
  Select -Expand Name

# Get all source names.
$sourceFiles = Get-ChildItem -File $getPath

# Perform the renaming, using the source file names, but keeping the
# target files' extensions.
$i = 0; $iVar = Get-Variable -Name i
Get-ChildItem -File $setPath | 
  Rename-Item -NewName { $sourceFiles[$iVar.Value++].BaseName + $_.Extension }

"
---- Target files AFTER RENAMING:"

Get-ChildItem -Name $setPath

# Clean up.
Remove-Item -Recurse $getPath, $setPath

Вышеуказанные выходы:

--- Source files:
s-file1.source-ext
s-file2.source-ext
s-file3.source-ext

---- Target files:
t-file1.target-ext
t-file2.target-ext
t-file3.target-ext

---- Target files AFTER RENAMING:
s-file1.target-ext
s-file2.target-ext
s-file3.target-ext

Обратите внимание, что целевые файлы теперь имеют базовые имена исходных файлов (s-file*), но исходные расширения целевых файлов (.target-ext).

Другие вопросы по тегам