2011-09-16 23 views
10

Estoy escribiendo un script que archiva los archivos para su análisis. Mi problema es que los nombres de los archivos no son únicos en varias carpetas, por lo que se están sobrescribiendo.Powershell Obtener carpeta principal de un archivo

Por ejemplo:

C:\StuffToCopy\Folder1\myFile1.txt 
C:\StuffToCopy\Folder1\myFile2.txt 
C:\StuffToCopy\Folder2\myFile1.txt 
C:\StuffToCopy\Folder2\myFile2.txt 

Al final de mi proceso de copia sólo estoy consiguiendo 2 archivos, pero quiero 4.

me gustaría que la salida sea así:

C:\ArchiveCopy\Folder1_myFile1.txt 
C:\ArchiveCopy\Folder1_myFile2.txt 
C:\ArchiveCopy\Folder2_myFile1.txt 
C:\ArchiveCopy\Folder2_myFile2.txt 

Aquí está mi script hasta ahora.

$files = dir -r -path "C:\StuffToCopy\" -i *.* 

foreach ($file in $files) 
{ 
    if ($file.LastWriteTime -gt (get-date).AddDays(-1)) { 
     copy -path $file C:\ArchiveCopy\ 
    } 
} 

quiero hacer algo como copy -path $file.FolderName & '_' & $file C:\ArchiveCopy\

No estoy seguro de cómo hacerlo.

Respuesta

13

Si $file es realmente un archivo - una instancia de System.IO.FileInfo (y no es realmente un directorio: System.IO.DirectoryInfo) entonces tiene la propiedad Directory que es una instancia de DirectoryInfo que tiene una Name:

$file | 
    copy-item -destination { 
    Join-Path C:\ArchiveCopy\ -childpath ($_.Directory.Name + "_" + $_.Name) } 

(Usando una ducto para iniciar porque el parámetro de -LiteralPathCopy-Item se unirá a la propiedad PSPath de la tubería, por lo que no hay necesidad de tirar el nombre del archivo original desde el objeto $file.)

Si $file podría ser un directorio, entonces usted necesita para hacer más del trabajo usted mismo, pero probablemente más fácil de filtrar los directorios primero:

dir -r -path C:\StuffToCopy\ | 
    where { -not $_.PSIsContainer } | 
    copy-item -destination { 
    Join-Path C:\ArchiveCopy\ -childpath ($_.Directory.Name + "_" + $_.Name) } 

Nota:

  • No hay necesidad de guardar toda la file objects and let the loop: let the pipeline do the looping
  • Sin necesidad de -i "*.*": este es el valor predeterminado de todos modos (y si necesita filtrar archivos en un patrón comodín, prefiera el parámetro -filter pattern: el filtro se pasa al sistema de archivos en lugar de creati ng. Objetos .NET y luego filtrándolos, que es mucho más lento si hay muchos archivos).
6

Prueba esto:

dir -r -path C:\StuffToCopy | 
     where {!$_.psiscontainer} | 
     copy -dest { "C:\ArchiveCopy\$($_.Directory.Name)_$($_.Name)"} 
3

Sobre la base de la secuencia de comandos, aquí hay otra manera de hacer esto:

$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 
    } 
} 
Cuestiones relacionadas