Reputation: 2398
I'm writing a script which archives files for analysis. My issue is that the file names aren't unique over multiple folders so they are being over written.
For instance:
C:\StuffToCopy\Folder1\myFile1.txt
C:\StuffToCopy\Folder1\myFile2.txt
C:\StuffToCopy\Folder2\myFile1.txt
C:\StuffToCopy\Folder2\myFile2.txt
At the end of my copy process I'm only getting 2 files, but I want 4.
I'd like the output to be like this:
C:\ArchiveCopy\Folder1_myFile1.txt
C:\ArchiveCopy\Folder1_myFile2.txt
C:\ArchiveCopy\Folder2_myFile1.txt
C:\ArchiveCopy\Folder2_myFile2.txt
Here's my script so far.
$files = dir -r -path "C:\StuffToCopy\" -i *.*
foreach ($file in $files)
{
if ($file.LastWriteTime -gt (get-date).AddDays(-1)) {
copy -path $file C:\ArchiveCopy\
}
}
I want to do something like copy -path $file.FolderName & '_' & $file C:\ArchiveCopy\
I'm just not sure how to do it.
Upvotes: 18
Views: 52680
Reputation: 3419
Based on your script, here's another way to do this:
$files = dir -r -path "C:\StuffToCopy\" -i *.*
$destPath = "c:\ArchiveCopy\"
foreach ($file in $files)
{
$folderPath = Split-Path $file.fullname -parent
$folder = Split-Path $folderPath -leaf
$destFilename = $folder + "_" + $file.name
$destFileFullPath = $destPath + $destFilename
write-host $destFileFullPath
if ($file.LastWriteTime -eq (get-date).AddDays(0)) {
copy -path $file $destFileFullPath
}
}
Upvotes: 8
Reputation: 126742
Try this:
dir -r -path C:\StuffToCopy |
where {!$_.psiscontainer} |
copy -dest { "C:\ArchiveCopy\$($_.Directory.Name)_$($_.Name)"}
Upvotes: 6
Reputation: 109005
If $file
is really a file – an instance of System.IO.FileInfo
(and not really a directory: System.IO.DirectoryInfo
) then it has property Directory
which is an instance of DirectoryInfo
which has a Name
:
$file |
copy-item -destination {
Join-Path C:\ArchiveCopy\ -childpath ($_.Directory.Name + "_" + $_.Name) }
(Using a pipeline to start because the -LiteralPath
parameter of Copy-Item
will bind to the PSPath
property from the pipeline, so no need to pull the original file's name from the $file
object.)
If $file
might be a directory, then you need to do more of the work yourself, but probably easier to filter out directories first:
dir -r -path C:\StuffToCopy\ |
where { -not $_.PSIsContainer } |
copy-item -destination {
Join-Path C:\ArchiveCopy\ -childpath ($_.Directory.Name + "_" + $_.Name) }
Note:
-i "*.*"
: this is the default anyway (and if you need to filter files on a wildcard pattern prefer the -filter pattern
parameter: the filter is passed to the filesystem rather than creating .NET objects and then filtering them which is much slower if there are a lot of files).Upvotes: 16