programing

PowerShell 복사 항목 사용 방법 및 구조 유지

i4 2023. 7. 25. 20:26
반응형

PowerShell 복사 항목 사용 방법 및 구조 유지

디렉토리 구조는 다음과 같습니다.

C:\folderA\folderB\folderC\client1\f1\files
C:\folderA\folderB\folderC\client1\f2\files
C:\folderA\folderB\folderC\client2\f1\files
C:\folderA\folderB\folderC\client2\f2\files
C:\folderA\folderB\folderC\client3\f1\files
C:\folderA\folderB\folderC\client4\f2\files

저는 다의내용복싶다습의 .f1:\를 가져오려면 Ctmp\에 있는 폴더를 하십시오.

C:\tmp\client1\f1\files
C:\tmp\client2\f1\files
C:\tmp\client3\f1\files

시도해 봤습니다.

Copy-Item -recur -path: "*/f1/" -destination: C:\tmp\

그러나 구조를 제대로 복사하지 않고 내용을 복사합니다.

PowerShell 버전 3.0 이상에서는 다음과 같은 방법으로 간단히 수행할 수 있습니다.

Get-ChildItem -Path $sourceDir | Copy-Item -Destination $targetDir -Recurse -Container

참조: 하위 항목 가져오기

PowerShell:

$sourceDir = 'c:\folderA\folderB\folderC\client1\f1'
$targetDir = ' c:\tmp\'

Get-ChildItem $sourceDir -filter "*" -recurse | `
    foreach{
        $targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
        New-Item -ItemType File -Path $targetFile -Force;
        Copy-Item $_.FullName -destination $targetFile
    }

참고:

  • -filter "*"는 아무 일도 하지 않습니다.일부 특정 파일을 복사하려는 경우 설명하기 위해 여기에 있습니다.예: 모든 *.config 파일.
  • 여전히 새 항목을 호출해야 합니다.-Force폴더 구조를 실제로 만듭니다.

저는 이 문제에 대한 많은 해결책을 찾았는데, 이 모든 것이 단순한 복사 항목 명령이 아니라 약간의 변화였습니다. 중 일부는 3. 3하여 PowerShell 3.0을 이 할 수 .-ContainerCopy-Item 파일:

Copy-Item $from $to -Recurse -Container

이것은 실행된 테스트이며 오류가 없으며 대상 폴더가 동일한 폴더 구조를 나타냈습니다.

New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt

# NOTE: with no \ at the end of the destination, the file
#       is created in the root of the destination, and
#       it does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container

# If the destination does not exist, this created the
# matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container

사용하다xcopy또는robocopy둘 다 정확히 그 목적을 위해 설계되었습니다.물론 경로가 파일 시스템 경로일 뿐이라고 가정합니다.

PowerShell을 사용하여 폴더 구조를 올바르게 복사하려면 다음과 같이 하십시오.

$sourceDir = 'C:\source_directory'
$targetDir = 'C:\target_directory'

Get-ChildItem $sourceDir -Recurse | % {
   $dest = $targetDir + $_.FullName.SubString($sourceDir.Length)

   If (!($dest.Contains('.')) -and !(Test-Path $dest))
   {
        mkdir $dest
   }

   Copy-Item $_.FullName -Destination $dest -Force
}

이렇게 하면 디렉터리를 만들고 파일을 복사할 수 있습니다.물론 폴더에 마침표가 있는 경우 위의 Contains() 호출을 수정하거나 언급한 대로 "f1"을 검색하려면 필터를 추가해야 합니다.

Container(복사 항목으로) 전환하여 폴더 구조를 유지 관리합니다.즐거운 시간 되세요.

testing>> tree

Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client2
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client3
│   └───f1
│       └───files
└───client4
    └───f2
        └───files

testing>> ls client* | % {$subdir = (Join-Path $_.fullname f1); $dest = (Join-Path temp ($_
.name +"\f1")); if(test-path ($subdir)){ Copy-Item $subdir $dest -recurse -container -force}}

testing>> tree

Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client2
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client3
│   └───f1
│       └───files
├───client4
│   └───f2
│       └───files
└───temp
    ├───client1
    │   └───f1
    │       └───files
    ├───client2
    │   └───f1
    │       └───files
    └───client3
        └───f1
            └───files

testing>>

파이프나 인라인 스크립팅이 필요 없는 보다 간단한 방법을 찾는 데 시간을 투자한 이후로:

Copy-Item -Path $sourceDir -Destination $destinationDir -Recurse -Container -Verbose

▁a▁다▁also를 제공할 수도 있습니다.-Filter복사에 대한 조건이 요구되는 경우 인수.

PowerShell 5.1.18362.752와 함께 작동합니다.

출처: https://devblogs.microsoft.com/scripting/powertip-use-powershell-to-copy-items-and-retain-folder-structure/

같은 작업을 수행해야 했기 때문에 다음 명령을 찾았습니다.

XCopy souce_path destination_path /E /C /I /F /R /Y

그리고 당신의 경우:

XCopy c:\folderA\folderB\folderC c:\tmp /E /C /I /F /R /Y

또한 일부 항목을 제외해야 하는 경우 제외 목록이 있는 텍스트 파일을 만듭니다.예:

텍스트 파일 'exclude'를 만듭니다.드라이브 C:\에 txt'를 입력하고 다음을 추가합니다.

.svn
.git

복사 명령은 다음과 같습니다.

XCopy c:\folderA\folderB\folderC c:\tmp /EXCLUDE:c:\exclude.txt /E /C /I /F /R /Y

다음은 원본 파일이 상대적이고 일부 파일만 폴더 구조로 복사하면 되는 기본 질문의 약간 변형입니다.는 이시리실경수있발다습니생할을 할 수 .git diff변경 사항의 하위 집합을 가지고 있습니다.예.

src/folder1/folder2/change1.txt      
src/folder3/change2.txt   
->   
c:\temp

코드

# omitting foreach($file in $files)
$file = 'src/folder1/folder2/change1.txt'
$tempPath = 'c:\temp'

# Build destination path
$destination = Join-Path $tempPath -ChildPath (Split-Path $file)

# Copy and ensure destination exists
Copy-Item -Path $file -Destination (New-Item -Path $destination -Type Directory -Force)

는 다음과 .
c:\folder\src\folder1\folder2\change1.txt
c:\folder\src\folder3\change2.txt

스크립트의 주요 기술은 폴더 구조를 평가하고 New-Item 명령을 사용하여 폴더 구조가 생성되는지 확인하는 것입니다.

$sourceDir = 'C:\source_directory'
$targetDir = 'C:\target_directory'

Get-ChildItem $sourceDir -Recurse | % {
   $dest = $targetDir + $_.FullName.SubString($sourceDir.Length)

   If (!($dest.Contains('.')) -and !(Test-Path $dest))
   {
        mkdir $dest
   }

   Copy-Item $_.FullName -Destination $dest -Force
}

이 코드는 특히 필터/where-object 메서드와 관련하여 Get-ChildItem을 사용하는 경우에 작동합니다.

그러나 이 코드에는 한 가지 사소한 오류가 있습니다."IF" 문과 다음 코드 "mkdir"를 통해 $targetDir의 폴더가 생성됩니다.나중에 "copy-item" 명령을 실행하면 "copy-dir" 명령을 실행하면 폴더 내에 동일한 폴더가 생성됩니다.


다음은 "Where-Object" 기능을 사용하여 작동한 예입니다.단순히 IF 문을 생략할 수 있습니다.

$Sourcefolder= "C:\temp1"
$Targetfolder= "C:\temp2"


$query = Get-ChildItem $Sourcefolder -Recurse | Where-Object {$_.LastWriteTime -gt [datetime]::Now.AddDays(-1)}
$query | % {
    $dest = $Targetfolder + $_.FullName.SubString($Sourcefolder.Length)
    Copy-Item $_.FullName -Destination $dest -Force
}

경로가 끝에 "\"로 표시되지 않는지 확인합니다.

아래는 저에게 효과가 있었습니다.

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "target=e:\backup"

    for /f "usebackq delims=" %%a in ("TextFile.txt") do (
        md "%target%%%~pa" 2>nul
        copy /y "%%a" "%target%%%~pa"
    )

목록 내의 각 줄(파일)에 대해 대상 폴더 아래에 읽기 줄에 표시된 것과 동일한 경로를 만듭니다(%%~pa는 %%a가 참조하는 요소의 경로입니다).그런 다음 읽기 파일을 대상 폴더에 복사합니다.

Copy-Item은 사용자가 예상하는 것을 수행하지 않습니다. Invoke-Expression은 명령줄 명령을 호출하고 파워셸 변수를 사용할 수 있습니다.디렉토리가 복사되도록 (빈 디렉토리도 포함) /Y와 함께 good-old xcopy 명령을 사용하여 프롬프트 표시를 억제하고 덮어쓰기를 확인합니다.

$sourceDir = "c:\source\*"
$targetDir = "c:\destination\"
Invoke-Expression "xcopy $sourceDir $targetDir /E /Y"

일반적으로 복사 항목은 대상 폴더가 이미 존재하는 한 이 작업을 수행합니다.문서가 제가 테스트를 통해 검증한 것과 일치하지 않습니다.대상 경로의 후행 슬래시는 이 문제를 해결하지 않습니다.폴더 계층을 복사할 때 -Recurse를 사용해야 합니다.Container 매개 변수는 기본적으로 true로 설정되어 있으므로 이를 해제할 수 있습니다.

질문에서 명명된 하위 폴더를 기준으로 복사할 파일 목록을 필터링하고 있습니다.Copy-Item의 Path 속성에 대해서는 작동하지만, 문제는 대상 폴더(클라이언트*)가 존재하지 않기 때문에 파일이 대상 폴더의 루트에 배치된다는 것입니다.대부분의 다른 답변은 이 시나리오를 구체적으로 다루지 않으므로 질문에 대답하지 않습니다.솔루션을 달성하려면 다음 두 단계를 수행해야 합니다.

  1. 복사할 파일 선택
  2. 대상 폴더가 있는지 확인하면서 선택한 파일을 대상 폴더에 복사
$source = 'C:\FolderA\FolderB\FolderC'
$dest = 'C:\tmp'
# Only need the full name
$files = Get-ChildItem -Path $source -Recurse -File | Where-Object { $_.FullName -match '^.+\\client\d\\f1\\.+\..+$' } | ForEach-Object { $_.FullName }

# Iterate through the list copying files
foreach( $file in $files ) {
    $destFile = $file.Replace( $source, $dest )
    $destFolder = Split-Path -Path $destFile -Parent

    # Make sure the destination folder for the file exists
    if ( -not ( Test-Path -Path $destFolder ) ) {
        New-Item -Path ( Split-Path -Path $destFolder -Parent ) -Name ( Split-Path -Path $destFolder -Leaf ) -ItemType Directory -Force
    }
    
    Copy-Item -Path $file -Destination $destFolder
}
$source ="c:\"
$destination="c:\tmp"
sl $source
md $destination
ls "." -rec -Filter *.zip | %{
$subfolder=($_.FullName)
$pathtrim=($subfolder -split [regex]::escape([system.io.path])::directoryseperatorchar)[-3] # update -2,-3 here to match output, we need 'client1\f1\files' here 
echo $pathtrim
$finaldest=Join-Path -Path $destination -ChildPath $pathtrim
cp $source $finaldest -Verbose
}

폴더 구조를 유지하는 디렉터리에서 모든 파일을 복사하는 다음 기능을 만들었습니다.그런 다음 폴더 구조가 시작될 시작 색인을 지정할 수 있습니다.

    function Copy-FileKeepPath {

    param (
        $filter,$FileToCopy,$des,$startIndex
    )
    Get-ChildItem -Path $FileToCopy -Filter $filter -Recurse -File | ForEach-Object {
        $fileName = $_.FullName
        #Remove the first part to ignore from the path.
        $newdes=Join-Path -Path $des -ChildPath $fileName.Substring($startIndex)
        $folder=Split-Path -Path $newdes -Parent
        $err=0
    
        #check if folder exists"
        $void=Get-Item $folder -ErrorVariable err  -ErrorAction SilentlyContinue
        if($err.Count -ne 0){
          #create when it doesn't
          $void=New-Item -Path $folder -ItemType Directory -Force -Verbose
        }

        $void=Copy-Item -Path $fileName -destination $newdes -Recurse -Container -Force -Verbose
    }
}

다음과 같이 사용합니다.

Copy-FileKeepPath -FileToCopy 'C:\folderA\folderB\folderC\client1\f1\' -des "C:\tmp" -filter * -startIndex "C:\folderA\folderB\folderC\".Length

라이브러리 파일(플랫폼 및 빌드 유형이 서로 다름)만 공유하려는 비슷한 요구사항이 있었습니다.PowerShell 스크립트를 작성하려고 했는데 "SyncBackFree" 도구를 사용하여 1분 이내에 완료할 수 있다는 것을 깨달았습니다.예상대로 작동했습니다.

프로파일 작성

소스 및 대상 폴더 선택

하위 디렉토리 및 파일 선택을 누릅니다.

왼쪽 "필터 변경" 클릭

파일 확장자("*.lib") 및 "*"(폴더 구조용) 추가

enter image description here

언급URL : https://stackoverflow.com/questions/5432290/how-to-use-powershell-copy-item-and-keep-structure

반응형