Copy file names from one folder to another while keeping the original extensions

雨燕双飞 提交于 2019-12-23 00:41:50

问题


I need help with copying file names (not the files themselves) from C drive to D drive. I was able to find the following powershell code online:

$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++
}

This code successfully renames/copies all file names from C:\MyFiles to D:\MyFiles, strictly by corresponding positions (indices in the enumeration).

However, it is also updating the extensions, so for instance:

C:\MyFiles\myfile.txt renames D:\MyFiles\thisfile.docx to D:\MyFiles\myfile.txt

Is there a way to edit the Powershell code to only rename the base of the filename (e.g., myFile) while keeping the target files' extensions (e.g., .docx)?

So that C:\MyFiles\myfile.txt renames D:\MyFiles\thisfile.docx to D:\MyFiles\myfile.docx, using the


回答1:


It sounds like you want to rename files in a target directory positionally, based on corresponding files in a source directory - while retaining the target directory files' extensions:

$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 }
  • To preview the resulting filenames, append -WhatIf to to the Rename-Item call.

  • The .BaseName property of the [System.IO.FileInfo] objects output by Get-ChildItem returns the file-name portion without the extension.

  • $_.Extension extracts the input file's (i.e., the target file's) existing extension, including the leading .

  • Note that the script block ({ ... }) passed to Rename-Item creates a child variable scope, so you cannot increment a variable in the caller's scope directly (it would create a new copy of such a variable with the original value every time); therefore, a [ref] instance is created to indirectly hold the number, which the child scope can then modify via the .Value property.


Here's a complete example:

Note: While this example uses similar file names and uniform extensions, the code works generically, with any names and extensions.

# 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

The above yields:

--- 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

Note how the target files now have the source files' base file names (s-file*), but the target files' original extensions (.target-ext).



来源:https://stackoverflow.com/questions/49889577/copy-file-names-from-one-folder-to-another-while-keeping-the-original-extensions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!