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
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 theRename-Item
call.The
.BaseName
property of the[System.IO.FileInfo]
objects output byGet-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 toRename-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