[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
  1. @echo off
  2. setlocal ENABLEDELAYEDEXPANSION
  3. chcp 936
  4. set path=%pathgnu%;%path%
  5. set sour=新建文件夹
  6. set dest=%~n0
  7. set exclude=QQ
  8. if exist %dest% rd /s /q %dest%
  9. if not exist %dest% mkdir %dest%
  10. call :C_timer
  11. set "_cmd_=dir /s /b %sour%\*.txt | sed -r -e "s/^.+[\]//" | sort -u"
  12. set _cmdsed_=-r -e "/%exclude%/d" -e "/^\S+\s+\S+\s+\S+$/^!d" -e "s/SH/0/" -e "s/SZ/1/" -e "s/\s+/^|/g"
  13. set _cmdawk_=" { arr[$0]++ ; if ( arr[$0] == 1 ) { print $0 } } "
  14. for /f "usebackq tokens=* delims=" %%a in (`cmd /c "%_cmd_%"`) do (
  15.     echo %%a
  16.     (
  17.         for /f "usebackq tokens=* delims=" %%b in (`dir /s /b "%sour%\%%a"`) do (
  18.             type "%%~fb"
  19.         ) | sed -r -e $a\
  20.     ) | sed !_cmdsed_! | awk !_cmdawk_! > "%dest%\%%~nxa"
  21. )
  22. call :C_timer sum
  23. exit/b
  24. rem del %dest%\*.tmp
  25. :C_timer
  26. if not defined _ti_ set _ti_=-1
  27. set/a _ti_+=1
  28. set _tb_=%_te_%
  29. set _te_=%time%
  30. if %_ti_% EQU 0 (
  31.     set _tb_=%_te_%
  32. )
  33. set/a _tdiff_=(9%_te_:~0,2%-9%_tb_:~0,2%)*360000+(9%_te_:~3,2%-9%_tb_:~3,2%)*6000+(9%_te_:~6,2%%_te_:~9,2%-9%_tb_:~6,2%%_tb_:~9,2%)
  34. set/a _tdiff_=%_tdiff_:-=8640000-%
  35. set/a _tdiffSum_+=%_tdiff_%
  36. if "%_ti_%" == "0" (
  37.     (echo,) >>time.txt
  38.     (echo %~nx0  %_ti_%  %_te_%) >>time.txt
  39. ) else (
  40.     (echo %~nx0  %_ti_%  %_te_%  %_tdiff_:~0,-2%.%_tdiff_:~-2%) >>time.txt
  41. )
  42. if %1.==sum. (
  43.     (echo %~nx0                  %_tdiffSum_:~0,-2%.%_tdiffSum_:~-2%) >>time.txt
  44. )
  45. goto :eof
复制代码

TOP

本帖最后由 newswan 于 2021-10-9 12:55 编辑

回复 52# xczxczxcz


可以在vbs里加个计时器,完成后显示时长
这样时间比较准确

TOP

原VSCODE调试50秒,
今优化了两点:I/O读取和范型数据处理,现缩短至平均24秒(23.7XX~24.2XX)。(按顶楼的要求和网盘文件)

视频被百度转码变成卡顿了

第一个视频为前台处理:约24秒
https://pan.baidu.com/s/1VXnS_n6mE457iUp-rLk8Hg

第二个视频为后台处理:约28秒
https://pan.baidu.com/s/1S6Dl1KqAus_QpBVkTcOYWw
QQ: 己阵亡
脚本优先 [PowerShell win10]

TOP

本帖最后由 newswan 于 2021-10-8 17:54 编辑

同名文件分组,流式处理
需要 sed awk sort
  1. @echo off
  2. setlocal ENABLEDELAYEDEXPANSION
  3. set sour=新建文件夹
  4. set dest=%~n0
  5. set exclude=QQ
  6. set "_cmd_=dir /s /b %sour%\*.txt | sed -r -e "s/^.+[\]//" | sort -u"
  7. set _cmdsed_=-r -e "/%exclude%/d" -e "/^\S+\s+\S+\s+\S+$/^!d" -e "s/SZ/1/" -e "s/SH/0/" -e "s/\s+/^|/g"
  8. set _cmdawk_=" { arr[$0]++ ; if ( arr[$0] == 1 ) { print $0 } } "
  9. for /f "usebackq tokens=* delims=" %%a in (`cmd /c "%_cmd_%"`) do (
  10.     echo %%a
  11.     (
  12.         for /f "usebackq tokens=* delims=" %%b in (`dir /s /b "%sour%\%%a"`) do (
  13.             type "%%~fb"
  14.         ) | sed -r -e $a\
  15.     ) | sed !_cmdsed_! | awk !_cmdawk_! > "%dest%\%%~nxa"
  16. )
复制代码
ps: linux 的 sort 不是 windows自带的

TOP

本帖最后由 WHY 于 2021-10-10 21:55 编辑

Test.vbs
  1. Rem On Error Resume Next
  2. Dim srcDir, dstDir
  3. srcDir = "E:\Test\新建文件夹"           '源文件夹路径,需替换为实际路径
  4. dstDir = "E:\Test\新建文件夹1"          '目标文件夹路径
  5. Dim wsc
  6. Set wsc = CreateObject("WScript.Shell")
  7. If WSH.Arguments.Count = 0 Then
  8.     wsc.Run "cscript " & chr(34) & WSH.ScriptFullName & chr(34) & " ARG", 0
  9.     WScript.Quit
  10. End If
  11. Dim dic1, fso
  12. Set dic1 = CreateObject("Scripting.Dictionary")
  13. Set fso  = CreateObject("Scripting.FileSystemObject")
  14. Dim reg
  15. Set reg     = New RegExp
  16. reg.Pattern = "[ \t]+"
  17. reg.Global  = True
  18. Dim objExec
  19. If Not fso.FolderExists(srcDir) Then MsgBox "源文件夹不存在" : WSH.Quit
  20. wsc.Run "cmd /c md " & chr(34) & dstDir & chr(34) & " 2>nul", 0              '创建目标文件夹
  21. Set objExec = wsc.Exec( "cmd /c dir /b /a-d /s " & chr(34) & srcDir & "\*.txt" & chr(34) )  '遍历源文件夹
  22. Rem 字典dic1,key=文件名,value=文件路径
  23. Dim strFilePath, strFileName
  24. Do Until objExec.StdOut.AtEndOfStream
  25.     strFilePath = objExec.StdOut.ReadLine
  26.     strFileName = fso.GetFile(strFilePath).Name
  27.     strFileName = LCase(strFileName)
  28.     If Not dic1.Exists(strFileName) Then
  29.         dic1.Add strFileName, strFilePath
  30.     Else
  31.         dic1.Item(strFileName) = dic1.Item(strFileName) & vbLf & strFilePath
  32.     End If
  33. Loop
  34. Rem 遍历字典dic1
  35. Dim key
  36. For Each key In dic1.Keys
  37.     GetFileContent key, Split( Dic1.Item(key), vbLf )
  38. Next
  39. Function GetFileContent(fileName, ByRef arrFilePath)
  40.     Dim dic2, i, objFile, strLine
  41.     Set dic2 = CreateObject("Scripting.Dictionary")
  42.     For i = 0 To UBound(arrFilePath)
  43.         Set objFile = fso.OpenTextFile(arrFilePath(i), 1)
  44.         Do Until objFile.AtEndOfStream
  45.             strLine = objFile.ReadLine
  46.             strLine = reg.Replace(strLine, "|")                                       '空格替换为"|"
  47.             If UBound(Split(strLine, "|")) >= 2 And InStr(strLine, "-QQ") <= 0 Then   '如果大于等于3列、不含 "-QQ"
  48.                 strLine = Replace(Replace(strLine,"SZ", "0|"),"SH", "1|")             '替换 "SZ" 和 "SH"
  49.                 If Not dic2.Exists(strLine) Then                                      '字典dic2,用于去重复
  50.                     dic2.Add strLine, True
  51.                 End If
  52.             End If
  53.         Loop
  54.         objFile.Close
  55.         Set objFile = Nothing
  56.     Next
  57.     fso.OpenTextFile(dstDir & "\" & fileName, 2, True).Write( Join(dic2.Keys, vbCrLf) )    '保存
  58.     Set dic2 = Nothing
  59. End Function
  60. MsgBox "Done"
复制代码
Test.PS1
  1. $dt = get-Date;
  2. $srcDir = 'E:\Test\新建文件夹';
  3. $dstDir = 'E:\Test\新建文件夹1';
  4. If (![IO.Directory]::Exists($dstDir)){ $null = md $dstDir }
  5. $dic = New-Object 'System.Collections.Generic.Dictionary[string, [Collections.ArrayList]]';
  6. forEach( $file In (dir $srcDir -Recurse -Filter '*.txt') ){
  7.     $Name = $file.BaseName.ToUpper();
  8.     $Path = $file.FullName;
  9.     if( !$dic.ContainsKey($Name) ){
  10.         $dic.Add($Name, @($Path));
  11.     } else {
  12.         [void]$dic[$Name].Add($Path);
  13.     }
  14. }
  15. forEach( $key In $dic.Keys ){
  16.     $Hash = @{};
  17.     for( $i=0; $i -lt $dic[$key].Count; $i++ ){
  18.         $arr = [IO.File]::ReadAllLines($dic[$key][$i], [Text.Encoding]::Default);
  19.         $arr = $arr -match '^(?:(?!-QQ)\S)+\s+\S+\s+\S+';
  20.         $arr = $arr -replace '\s+', '|' -replace 'SZ', '0|' -replace 'SH', '1|';
  21.         $Count = $arr.Count;
  22.         for( $j=0; $j -lt $Count; $j++ ){
  23.             if( !$Hash.ContainsKey($arr[$j]) ){
  24.                 $Hash.Add($arr[$j], $True);
  25.             }
  26.         }
  27.     }
  28.     [IO.File]::WriteAllLines( $dstDir + '\' + $key + '.txt', $Hash.Keys );
  29. }
  30. ((get-Date) - $dt).TotalSeconds;
复制代码

TOP

相当于
  1. $null =
复制代码

TOP

回复 47# idwma


     估计是[void]直接强转成了$null才不会输出

TOP

回复 44# newswan


    看went的代码发现一个[void],把空输出改成这个瞬间起飞呀
  1. Get-ChildItem -path $dest *.tmp | foreach-object {
  2.     $reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $_.fullname
  3.     $aa=New-Object System.Collections.Generic.HashSet[string]
  4.     $_.fullname
  5.     $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
  6.     while ( $read = $reader.ReadLine() ) {
  7.         [void]$aa.add($read)
  8.     }
  9.     [IO.File]::WriteAllLines($filename,$aa)
  10. }
复制代码

TOP

回复 45# went


    线程不要设置过多,不然cpu容易爆满

TOP

可以尝试下多线程,线程数越多越快,取决你的cpu
数据处理函数可以自行优化
  1. #&cls&cd /d "%~dp0" & @powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" & pause&exit
  2. cls
  3. $t1 = Get-Date
  4. $src_dir = '新建文件夹'
  5. $dst_dir = 'out'
  6. [void][System.IO.Directory]::CreateDirectory($dst_dir)
  7. #线程函数 处理数据
  8. $HandleGroupJob = {
  9.     #线程参数
  10.     param($dst_dir,$groupInfo)
  11.     Write-Host $groupInfo.Name
  12.     #汇总去重并筛选
  13. $set = New-Object 'System.Collections.Generic.HashSet[string]'
  14.     & { $groupInfo.Group | foreach { [IO.File]::ReadAllLines($_.FullName)} } | foreach {
  15. if($_ -match '\S+\s+\d+\s+-?\d{2,}'){
  16. [void]$set.Add(($_ -replace 'SH','1|' -replace 'SZ','0|' -replace '\s+','|'))
  17. }
  18. }
  19.     #输出
  20.     Out-File -InputObject $set -FilePath ('{0}\{1}' -f $dst_dir,$groupInfo.Name)
  21. $set = $null
  22.     return ($groupInfo.Name + ' 已完成')
  23. }
  24. #多线程设置
  25. $pool = [runspacefactory]::CreateRunspacePool(1,10) #最多10个线程并发
  26. $pool.Open()
  27. $threads = New-Object 'System.Collections.ArrayList'
  28. $results = New-Object 'System.Collections.ArrayList'
  29. '开始创建线程...'
  30. Get-ChildItem -Recurse -Path $src_dir -Filter '*.txt' | Group-Object {$_.Name} | foreach {
  31.     $_.Name
  32.     $thread = [powershell]::Create()
  33.     $thread.RunspacePool = $pool
  34.     [void]$thread.AddScript($HandleGroupJob)
  35.     [void]$thread.AddArgument($dst_dir)
  36.     [void]$thread.AddArgument($_)
  37.     [void]$threads.Add($thread)
  38.     [void]$results.Add($thread.BeginInvoke())
  39. }
  40. '-------------------------------'
  41. '等待线程结束'
  42. while($true){
  43.     $all_done = $true
  44.     for($i = 0; $i -lt $results.Count; $i++){
  45.         if($results[$i] -ne $null){
  46.             if($results[$i].IsCompleted){
  47.                 $threads[$i].EndInvoke($results[$i])
  48. $threads[$i].Dispose()
  49. $threads[$i] = $null
  50.                 $results[$i] = $null
  51. [System.GC]::Collect()
  52.             } else {
  53.                 $all_done = $false
  54.             }
  55.         }
  56.     }
  57.     if($all_done){ break }
  58.     Start-Sleep -Milliseconds 500
  59. }
  60. #关闭线程池
  61. $pool.Close()
  62. '-------------------'
  63. '{0}  -> {1}' -f $t1,(Get-Date)
复制代码

TOP

一段时间不用,很多都不熟悉了啊

TOP

回复 42# idwma


谢谢,这个用时是 unix 工具的 6 倍,比前面的要好多了

TOP

本帖最后由 idwma 于 2021-10-6 16:17 编辑

回复 40# newswan

去重的部分抄前辈的试试看快不快http://www.bathome.net/thread-25194-2-1.html
  1. Get-ChildItem -path $dest *.tmp | foreach-object {
  2.     $reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $_.fullname
  3.     $aa=New-Object System.Collections.Generic.HashSet[string]
  4.     $_.fullname
  5.     $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
  6.     while ( $read = $reader.ReadLine() ) {
  7.         out-null -InputObject $aa.add($read)
  8.     }
  9.     [IO.File]::WriteAllLines($filename,$aa)
  10. }
复制代码
2

评分人数

    • PCL0769: 谢谢老师出手帮助!高技术!高人品!技术 + 1
    • newswan: 谢谢技术 + 1

TOP

回复 31# xczxczxcz
老师好!能将这个PS发出来吗?谢谢!

TOP

本帖最后由 newswan 于 2021-10-5 21:07 编辑

回复 39# idwma


谢谢指点
net 没学过。。。
合并效率一样了,去重,还是很慢
  1. $sour = "D:\share\tech\New folder\新建文件夹"
  2. $dest = "D:\share\tech\New folder\ccc2"
  3. $exclude = "QQ"
  4. Remove-Item $dest\*.*
  5. ( $MyInvocation.MyCommand.Name + "  1  " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
  6. Get-ChildItem -path $sour *.txt -Recurse | foreach-object {
  7.     $_.fullname
  8.     $filename = Join-Path -path $dest -ChildPath ($_.basename + ".tmp")
  9.     $a=( [IO.File]::ReadAllLines($_.fullname) )
  10.     $a = $a -match "\S+\s+\S+\s+\S+" -notmatch $exclude -replace "SZ","1" -replace "SH","0" -replace "\s+","|"
  11.     [IO.File]::AppendAllLines([string]$filename , [string[]]$a)
  12. }
  13. ( $MyInvocation.MyCommand.Name + "  2  " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
  14. Get-ChildItem -path $dest *.tmp | foreach-object {
  15.     $_.fullname
  16.     $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
  17.     $ht = @{}
  18.     $a = ( [IO.File]::ReadAllLines($_.fullname) )
  19.     $a = $a | foreach-object {
  20.         if ( -not ( $ht.ContainsKey($_) ) )
  21.         {
  22.             $_
  23.             $ht.add($_,"1")
  24.         }
  25.     }
  26.     $a | out-file -Encoding utf8 $filename
  27. }
  28. ( $MyInvocation.MyCommand.Name + "  3  " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
复制代码
1

评分人数

    • PCL0769: 谢谢老师出手帮助!高技术!高人品!技术 + 1

TOP

返回列表