
我實際上與 Batch 或 PowerShell 沒有任何真正的接觸點,不過,我已經設定了一個員工目錄,我現在正在為其尋找解決方案,其中文件透過腳本自動複製到上述目錄中:
- 目前要複製的文件都在一個資料夾中,應複製到該目錄的對應子資料夾中。
- 文件的檔案名稱結構如下,其中
XX
/XXXX
是在賦值中起作用的變數:ABCD_123456_1234567_12345_XX.pdf
ABCD_123456_1234567_12345_XXXX.pdf
- 目標目錄也包含這些,目前大約有五十個不同的目錄
是否可以只指向第三個底線和檔案副檔名之間的變量,因為這些變數會有所不同,可能會添加三位數或五位數變數?
- 我已經使用了搜尋功能,但沒有找到與給定範例完全對應的內容:
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
- 拆分基本名稱(即不含擴展名的檔案名稱)
_
並獲取基本名稱的最後一部分並將其保存在$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
此命令將建立一個資料夾(如果不存在),然後貼上該文件,如果文件存在於資料夾內,它將覆蓋該文件
更新:
尋找不帶副檔名的檔案名稱的命令(並將結果附加到 filenamewithoutext.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 = ...
,然後對該定義中的變數進行相同的操作。也將分配與首次使用結合。結果是:
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
}
}
}
讀起來很糟糕,但對於大數據集來說應該是值得的。