Board logo

标题: [问题求助] PowerShell怎样将子文件夹及其内容平均复制到另一个文件夹下的多个子文件夹中 [打印本页]

作者: 5i365    时间: 2021-12-17 12:48     标题: PowerShell怎样将子文件夹及其内容平均复制到另一个文件夹下的多个子文件夹中

本帖最后由 5i365 于 2021-12-18 20:51 编辑

又遇到一个平均分配的问题, 描述如下:

1文件夹下有11个子文件夹,分别是 a, b, c, d, e, f, g, h, i, j, k   实例情况可能会有%folder1_sub_count%个, 而且它们的下一级可能还有文件或文件夹等内容

2文件夹下有4个子文件夹,分别是  A, B, C, D, 实例情况可能会有%folder2_sub_count%个

想把1文件夹下所有的子文件夹及其下的内容, 平均复制到2文件夹下的多个子文件夹中, 这里会有一个不能均分的情况, 那就把1文件夹余下的, 放到2的最后一个文件夹中

上面的例子,期待的结果是:
1文件夹下的 a 和 b 和 c 子文件夹放到的2文件夹下的A文件夹中
1文件夹下的 d 和 e 和 f 子文件夹放到的2文件夹下的B文件夹中
1文件夹下的 g 和 h 和 i 子文件夹放到的2文件夹下的C文件夹中
1文件夹下的 j 和 k 子文件夹放到的2文件夹下的D文件夹中

另外,实际情况中的文件夹或子文件夹的名字,可能会是数字, 或会有数字开头, 或文件名中有空格等情况

作者: for_flr    时间: 2021-12-17 17:37

本帖最后由 for_flr 于 2021-12-17 17:38 编辑
  1. $d1="C:\Users\lenovo\Desktop\1"
  2. $d2="C:\Users\lenovo\Desktop\2"
  3. $dir1=Get-ChildItem $d1|Where-Object{$_.PSIsContainer -eq $true}
  4. $dir2=Get-ChildItem $d2|Where-Object{$_.PSIsContainer -eq $true}
  5. $num=$dir1.Count / $dir2.Count
  6. $num=[math]::Truncate($num)
  7. $mod=$dir1.Count % $dir2.Count
  8. $begin=0
  9. $end=$num
  10. $begin2=0
  11. $end2=$num-1
  12. for ($a=0;$a -lt $dir2.Count;$a++){
  13. if ($a -lt $mod){
  14.   Copy-Item $dir1[$begin..$end].fullname $dir2[$a] -WhatIf
  15.   $begin+=$num+1
  16.   $end+=$num+1
  17.   $begin2=$begin
  18.   $end2=$begin2+$num-1
  19.   
  20. }else{
  21.   Copy-Item $dir1[$begin2..$end2].fullname $dir2[$a] -WhatIf
  22.   $begin2+=$num
  23.   $end2+=$num
  24. }
  25. }
复制代码
powershell,测试没问题的话,就把-whatif 删掉
作者: for_flr    时间: 2021-12-17 17:40

powershell太吃力了,这个问题用批处理简单一些。
作者: 5i365    时间: 2021-12-17 20:40

本帖最后由 5i365 于 2021-12-18 20:03 编辑

回复 3# for_flr


    感谢大侠帮忙, 我把whatif删除了, 然后用下面的代码拷到.bat文件中, 能执行, 但是没有将文件拷到对应的文件夹中, 而是在桌面上新建了 A 和B 两个文件夹, 里面也缺少某个文件夹, 另外其子文件夹里的内容也没过去
示例文件打包下载:
https://wss1.cn/f/75c90piydb4 复制链接到浏览器打开
  1. #@&cls&powershell "type '%~0'|out-string|iex"&pause&exit
  2. $d1="C:\Users\Administrator\Desktop\1"
  3. $d2="C:\Users\Administrator\Desktop\2"
  4. $dir1=Get-ChildItem $d1|Where-Object{$_.PSIsContainer -eq $true}
  5. $dir2=Get-ChildItem $d2|Where-Object{$_.PSIsContainer -eq $true}
  6. $num=$dir1.Count / $dir2.Count
  7. $num=[math]::Truncate($num)
  8. $mod=$dir1.Count % $dir2.Count
  9. $begin=0
  10. $end=$num
  11. $begin2=0
  12. $end2=$num-1
  13. for ($a=0;$a -lt $dir2.Count;$a++){
  14. if ($a -lt $mod){
  15.   Copy-Item $dir1[$begin..$end].fullname $dir2[$a]
  16.   $begin+=$num+1
  17.   $end+=$num+1
  18.   $begin2=$begin
  19.   $end2=$begin2+$num-1
  20.   
  21. }else{
  22.   Copy-Item $dir1[$begin2..$end2].fullname $dir2[$a]
  23.   $begin2+=$num
  24.   $end2+=$num
  25. }
  26. }
复制代码

作者: 5i365    时间: 2021-12-18 20:05

回复 3# for_flr


    你好, 请问怎样实现把1文件中的那些文件随机均分到第2个文件夹中?  类似像我这样的问题, 搜索不到相关示例
作者: qixiaobin0715    时间: 2021-12-18 20:29

本帖最后由 qixiaobin0715 于 2021-12-18 20:55 编辑

批处理也能干这事:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /d %%a in (2\*) do (
  4.     set /a x+=1
  5.     set #!x!=%%a
  6. )
  7. for /d %%b in (1\*) do set /a y+=1
  8. set /a n=y/x
  9. set /a m=y%%x
  10. if !m! neq 0 set /a n+=1
  11. for /d %%c in (1\*) do (
  12.     set /a k+=1
  13.     set /a l=(k-1^)/n+1
  14.     for %%d in (#!l!) do (
  15.         if not exist "!%%d!\%%~nxc" (
  16.             md "!%%d!\%%~nxc"
  17.             xcopy "%%c\*.*" "!%%d!\%%~nxc\" /s>nul
  18.         )
  19.     )
  20. )
  21. pause
复制代码

作者: 5i365    时间: 2021-12-18 20:36

本帖最后由 5i365 于 2021-12-18 20:39 编辑

回复 6# qixiaobin0715


    能用ps实现下吗? 楼上那位朋友的代码, 我看不太明白,

在我印象中, 一堆的CMD代码, 用ps来实现, 几行就搞定了, 而且有的示例代码,理解起来不太吃力

另外, 能实现随机均分吗? 现在分过去的文件夹名字是升序的 例如 a b c d

我用这个主要是想给学生随机分卷了, 以前是手动拖, 感觉批处理还是快点
作者: 5i365    时间: 2021-12-18 20:41

回复 6# qixiaobin0715


    我刚才把1文件夹中的h子文件夹名,改成了2h 然后执行上面的代码, 会报错

以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
子目录或文件 \2h 已经存在。
作者: qixiaobin0715    时间: 2021-12-18 20:43

回复 7# 5i365
嘿嘿,ps学习中,水平不够。
作者: qixiaobin0715    时间: 2021-12-18 20:54

回复 8# 5i365
代码加个判断,已修改。
作者: 5i365    时间: 2021-12-18 20:59

回复 10# qixiaobin0715


    以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
以零为除数的错误。
请按任意键继续. . .

另外,实际情况中的文件夹或子文件夹的名字,可能会是数字, 或会有数字开头, 或文件名中有空格等情况
作者: qixiaobin0715    时间: 2021-12-18 21:16

我觉得是与文件名无关,应当是文件计数的问题,变量x、n为零会出现这种错误。抽空我再修改一下。
作者: 5i365    时间: 2021-12-18 22:51

回复 12# qixiaobin0715


    好像又没问题了, 前面不知道怎么回事
作者: taofan712    时间: 2021-12-18 22:51

本帖最后由 taofan712 于 2021-12-18 22:58 编辑
  1. $d1="C:\Users\administrator\Desktop\1"
  2. $d2="C:\Users\administrator\Desktop\2"
  3. $dir1=Get-ChildItem $d1|Where-Object{$_.PSIsContainer -eq $true}
  4. $dir2=Get-ChildItem $d2|Where-Object{$_.PSIsContainer -eq $true}
  5. $num=$dir1.Count / $dir2.Count
  6. $num=[math]::Truncate($num)
  7. $mod=$dir1.Count % $dir2.Count
  8. for ($a=0;$a -lt $dir2.Count;$a++){
  9. if ($mod -ne 0){
  10. Get-ChildItem $d1|Where-Object{$_.PSIsContainer -eq $true}|select-object -first ($num+1)|%{move $_.fullname $dir2[$a].fullname}
  11. }else{
  12. Get-ChildItem $d1|Where-Object{$_.PSIsContainer -eq $true}|select-object -first $num|%{move $_.fullname $dir2[$a].fullname}
  13. }
  14. $mod-=1
  15. }
  16. write-host "完成..."
  17. $null=[console]::readkey()
复制代码
这样呢,保存ps1文件。我是通过d1和d2的商和余数来写的。
五楼代码是另一台电脑写的,明天去看看错在哪里。。
作者: 5i365    时间: 2021-12-18 23:55

回复 14# taofan712


    感谢帮忙, 刚试了下, 可以了, 但是1文件夹内的所有文件全移走了, 不是复制到2文件夹下去的

另外, 能随机平均分配吗?  平时手动组卷也是连续的复制进去的, 要是能随机复制过去就太好了, 还是1文件夹下的那些子文件夹, 随机平均分配到2文件夹下的几个一级子文件夹下
作者: for_flr    时间: 2021-12-19 09:02

select-object -first改成get-random -count ,随机
move改成copy,复制
作者: qixiaobin0715    时间: 2021-12-19 13:39

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /d %%a in (2\*) do (
  4.     set /a x+=1
  5.     set #!x!=%%a
  6. )
  7. for /d %%b in (1\*) do (
  8.     set /a y+=1
  9.     set -!random!-!y!=%%b
  10. )
  11. set /a n=y/x
  12. set /a m=y%%x
  13. if !m! neq 0 set /a n+=1
  14. for /f "tokens=2 delims==" %%c in ('set -') do (
  15.     set /a k+=1
  16.     set /a l=(k-1^)/n+1
  17.     for %%d in (#!l!) do (
  18.         if not exist "!%%d!\%%~nxc" (
  19.             md "!%%d!\%%~nxc"
  20.             xcopy "%%c\*.*" "!%%d!\%%~nxc\" /s>nul
  21.         )
  22.     )
  23. )
  24. pause
复制代码

作者: 5i365    时间: 2021-12-19 20:10

回复 17# qixiaobin0715


    感谢分享, 感觉还是Powershell的代码好理解一些
作者: 5i365    时间: 2021-12-30 19:39

本帖最后由 5i365 于 2021-12-30 19:43 编辑

回复 16# for_flr


    你好, 如果现在不想给某个文件夹分配子文件夹了, 怎样在原来代码的基础上进行修改来实现想要的效果? 我的想法是: 把不给分配的文件夹名字定义到某个变量中 $bufenpei="B", 然后根据这个变量是否存在来决定给不给B分配文件夹

邮此产生的变动:
之前是把子文件夹均分到 A  B  C 三个文件夹中, 现在因为某些情况, 暂时不想给B分配了,  所产生的变动就是, 原来是分三份给A和B和C的, 现在是要分成两份给A和C了

感觉有点乱, 有点理不清头绪了

作者: for_flr    时间: 2021-12-31 09:29

回复 19# 5i365


    $dir2=Get-ChildItem $d2|Where-Object{$_.PSIsContainer -eq $true}
这一句不是获取文件夹2下的文件夹并写入变量dir2吗
在dir2中排除掉你不想分配的文件夹名字就行。get-childitem有个-exclude参数,表示不包括...不包括的内容用逗号依次隔开
  1. $dir2=Get-ChildItem $d2 -exclude A,B|Where-Object{$_.PSIsContainer -eq $true}
复制代码

作者: 5i365    时间: 2021-12-31 11:37

回复 20# for_flr


    感谢, exclude 排除的意思, 好理解一些, 但真是不会想到有个参数, 水平太菜了




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2