
실제로 Batch 또는 PowerShell과 관련된 실제 접점은 없지만 현재 솔루션을 찾고 있는 직원 디렉터리를 설정했습니다. 여기서 문서는 스크립트를 통해 앞서 언급한 디렉터리에 자동으로 복사됩니다.
- 복사할 문서는 현재 모두 하나의 폴더에 있으므로 디렉토리의 각 하위 폴더에 복사해야 합니다.
- 문서의 파일 이름은 다음과 같이 구성됩니다. 여기서
XX
/XXXX
는 과제에서 역할을 하는 변수입니다.ABCD_123456_1234567_12345_XX.pdf
ABCD_123456_1234567_12345_XXXX.pdf
- 대상 디렉토리에는 이러한 항목도 포함되어 있으며 현재 약 50개의 다른 항목이 있습니다.
세 번째 밑줄과 파일 확장자 사이의 변수만 가리키는 것이 가능합니까? 세 자리 또는 다섯 자리 변수를 추가하면 달라질 수 있습니까?
- 나는 이미 검색 기능을 사용했지만 주어진 예와 정확히 일치하는 것을 찾지 못했습니다.
C:\ABCD_123456_1234567_12345_99
→\\11/17/19/1991\Directory\99_ABCD\
C:\ABCD_123456_1234567_12345_9999
→\\11/17/19/1991\Directory\9999_ABCD\
- 아마도:
C:\ABCD_123456_1234567_12345_999
→\\11/17/19/1991\ directory\999_ABCD\
C:\ABCD_123456_1234567_12345_99999
→\\11/17/19/1991\Directory\99999_ABCD\
를 사용하여 설정하려고 시도했지만 $FileName-split
실제로는 작동하지 않았지만 30:27에서와 같이 실제로 파일 이름을 완성하여 실제로 계산할 수 있었습니다.
C:\ABCD_123456_1234567_12345_99
→C:\ABCD_123456_1234567_12345_0099
- 모든 폴더가 존재하고 파일 이름에 변수가 포함되어 대상 폴더를 구문 분석하는 데 어려움을 겪고 있습니다.
$Directory = "C:\Folder\" $FileNames = (Get-Item $Directory).GetFiles() foreach($FileName in $FileNames) { $Destination = "\\10.10.10.10\destinationfolder" { Move-Item -Path $FileName -Destination $Destination } }
일치 항목별로 파일을 이동할 수 있는 방법이 있습니까? 아니면 확인할 부분이 설정되도록 계산하여 모든 대상 폴더를 구문 분석해야 합니까?
이건 시각화할 수도 있겠네요
답변1
이는 PowerShell 솔루션입니다.
$Destination = "\\10.10.10.10\destinationfolder"
Get-ChildItem "C:\Folder" | ForEach-Object {
$Head = ($_.BaseName -split '_')[0]
$Tail = ($_.BaseName -split '_')[-1]
$DestinationPath = Join-Path $Destination ("{0}_{1}" -f $Head, $Tail)
New-Item -Path $DestinationPath -ItemType Directory -ErrorAction SilentlyContinue
Copy-Item $_.FullName $DestinationPath -Force
}
업데이트:
귀하의 의견에 따르면 이것이 귀하가 원하는 것 이상인 것 같습니다. 그러나 각 엔딩에는 정확히 일치하는 폴더가 하나씩 있는지 확인해야 합니다. 예를 들어 이름이 지정된 폴더가 있고 abc_123
이름이 지정된 다른 폴더가 있는 경우 def_123
첫 번째 폴더만 사용합니다. 귀하의 의견에 따르면 우리는 결말만 고려하기 때문입니다.
$Destination = "\\10.10.10.10\destinationfolder"
Get-ChildItem "C:\Folder" | ForEach-Object {
$Tail = ($_.BaseName -split '_')[-1]
$Filter = "*_{0}" -f $Tail
$DestDir = Get-ChildItem $Destination -Filter $Filter -Directory | Select-Object -ExpandProperty FullName -First 1
if ($DestDir) {
Copy-Item $_.FullName $DestDir -Force
} else {
"No Directory was found that matched the Filter {0} in Directory {1}" -f $Filter, $Destination | Write-Host
}
}
다음을 수행합니다.
$Destination
먼저 변수 에서 대상 폴더를 설정하십시오.- 다음을 사용하여 폴더의 모든 항목 가져오기
Get-ChildItem
(이를 재귀적으로 만들어야 하는 경우 특정 파일 유형 추가 또는 기타 확장-Recurse
만 원하는 경우 스위치를 추가하세요)-Filter *.txt
- 발견된 모든 파일을 반복합니다.
ForEach-Object
- Basename(확장자가 없는 파일 이름)을 분할
_
하고 Basename의 마지막 부분을 가져와서$Ending
변수 에 저장합니다. - 종료 변수를 다음과 같은 폴더 이름으로 형식화하여 폴더 이름을 계산합니다.
-f
Join-Path
대상과 계산된 폴더를 연결하여 저장하는 데 사용합니다 .$Destinationpath
- 폴더가 없으면 폴더를 만듭니다
New-Item
. 이미 존재하는 경우 이 줄은 기존 폴더를 덮어쓰지 않습니다. - 항목을 대상 폴더에 복사하십시오.
Copy-Item
답변2
질문을 이해하지 못하겠습니다. 하지만 이와 같은 파일을 복사하여 붙여넣고 싶으시다면
ABCD_123456_1234567_12345_1.txt copy into 1_ABCD
ABCD_123456_1234567_12345_2.txt copy into 2_ABCD
ABCD_123456_1234567_12345_3.txt copy into 3_ABCD
ABCD_123456_1234567_12345_9999.txt copy into 9999_ABCD
그렇다면 이 cmd 명령이 도움이 될 수 있습니다.
echo D|for /l %x in (1,1,20) do @xcopy ABCD_123456_1234567_12345_%x.txt ABC_%x\ /Y /Q
동일한 출력을 가진 두 번째 명령:
for /l %x in (1,1,20) do @xcopy ABCD_123456_1234567_12345_%x.txt ABC_%x\ /Y /Q
이 명령은 존재하지 않는 경우 폴더를 생성한 다음 파일을 붙여넣고 파일이 폴더 내에 존재하는 경우 파일을 덮어씁니다.
업데이트:
확장자 없이 파일 이름을 찾는 명령(그리고 결과를 filenamewithouttext.txt에 추가합니다)
for /f %x in ('dir /b') do @echo %~nx>>filenamewithoutext.txt
출력 파일 읽기 및 변수를 새 파일에 저장 variables.txt
for /f "tokens=5 delims=_" %x in (filenamewithoutext.txt) do @echo %x>>variables.txt
변수 읽기 및 파일을 다른 폴더에 복사
for /f %x in (variables.txt) do @xcopy ABCD_123456_1234567_12345_%x.txt ABC_%x\ /Y /Q
ABC_%x
당신은 로 변경할 수 있습니다%x_ABC
답변3
귀하의 질문을 읽으면서 이것이 효과가 있다고 생각합니다.
$Source = 'C:\Folder\'
$Destination = '\\10.10.10.10\destinationfolder\'
Get-ChildItem -Path $Source -FIlter *.pdf -File | ? { ($BaseName = $_.BaseName) -match '_' } | ForEach{
$Head = $BaseName.Split('_')[0]
$Tail = $BaseName.Split('_')[-1] ### (Index of -1) -> Last array element
$SubFolder = "$Tail`_$Head" ### *** Escaped <underscore> required ***
If ( Test-Path ( $FullPath = Join-Path $Destination $SubFolder ) ) {
Copy-Item -Literal $_.FullName $FullPath
} Else {
'"{0}" not copied because the directory "{1}" does not exist' -f $_.Name , $FullPath | Write-Output
}
}
ForEach-객체 • String.Split() 메서드 • 조인 경로 • 테스트 경로 • 복사항목
디버깅
저는 이 변형 코드를 사용하여 문자열 조작 문제를 해결했으며, 이를 통해 확장 문자열에 밑줄을 사용하는 문제를 발견했습니다. 모든 중간 변수를GridView
빠른 스캔을 위해:
Get-ChildItem -Path $Source -FIlter *.pdf -File | ? BaseName -match '_' | ForEach{
$Head = $_.BaseName.Split('_')[0]
$Tail = $_.BaseName.Split('_')[-1]
$SubFolder = "$Tail`_$Head"
$FullPath = Join-Path $Destination $SubFolder
[PSCustomObject]@{
'Head' = $Head
'Tail' = $Tail
'SubFolder' = $SubFolder
'FullPath' = $FullPath
'SubExists' = Test-Path $FullPath
}
} | Out-gridview
최적화
중간 변수는 개발/테스트/디버깅 중에는 훌륭하지만 이렇게 여러 번 실행되는 루프 내에서는 속도가 느려질 수 있습니다. 따라서 할당이 견고하다고 판단되면 먼저 $SubFolder
클립보드에 정의하는 표현식을 복사한 다음 $SubFolder
의 발생을 $FullPath = ...
괄호로 묶은 정의로 바꾼 다음 dis 해당 정의 내의 변수에 대해 동일하게 작업했습니다. 또한 처음 사용과 할당을 결합했습니다. 결과는 다음과 같습니다.
Get-ChildItem -Path $Source -FIlter *.pdf -File | ForEach{
If ( ($BaseName = $_.BaseName) -match '_' ) {
If ( Test-Path ( $FullPath=Join-Path $Destination "$($BaseName.Split('_')[-1])`_$($BaseName.Split('_')[0])" ) ) {
Copy-Item -Literal $_.FullName $FullPath
} Else {
'"{0}" not copied because the directory "{1}" does not exist' -f $_.Name , $FullPath | Write-Output
}
}
}
읽기는 힘들지만 대규모 데이터 세트에는 그만한 가치가 있습니다.