Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 将子文件夹向上移动一级的脚本(批处理或PowerShell)_Batch File_Powershell - Fatal编程技术网

Batch file 将子文件夹向上移动一级的脚本(批处理或PowerShell)

Batch file 将子文件夹向上移动一级的脚本(批处理或PowerShell),batch-file,powershell,Batch File,Powershell,我在Stackoverflow上发现了一些类似的问题,在尝试解决方案之后,我的问题仍然没有解决 以下是我的目录结构: D:\XYZ\Adam Jay\Adam Jay\files.txt D:\XYZ\Adam Jay\Adam Jay\SomeFolder\ D:\XYZ\Adam Jay\Adam Jay\OtherFolder\Some File.doc D:\XYZ\Mary Poppins\Mary Poppins\myOtherFile.txt 我有大约2000个 我的目标是按照上面

我在Stackoverflow上发现了一些类似的问题,在尝试解决方案之后,我的问题仍然没有解决

以下是我的目录结构:

D:\XYZ\Adam Jay\Adam Jay\files.txt

D:\XYZ\Adam Jay\Adam Jay\SomeFolder\

D:\XYZ\Adam Jay\Adam Jay\OtherFolder\Some File.doc

D:\XYZ\Mary Poppins\Mary Poppins\myOtherFile.txt

我有大约2000个

我的目标是按照上面的结构简单地删除多余的子文件夹。我只需手动剪切“sub-sub”文件夹“Adam Jay”并将其粘贴到XYZ中,在XYZ中替换或合并为更高级别的“Adam Jay”(随它移动任何文件和文件夹)

预期结果:

D:\XYZ\Adam Jay\files.txt

D:\XYZ\Adam Jay\SomeFolder\

D:\XYZ\Adam Jay\OtherFolder\Some File.doc

D:\XYZ\Mary Poppins\myOtherFile.txt

我对批处理脚本知之甚少,对PowerShell也一无所知。通过修改我在StackOverflow上找到的一个脚本,我成功地把事情搞糟了(幸运的是,它是一个测试目录)。[我玩的脚本可以在这里找到: ]

如果有人能帮我解决这个问题,那就太好了。我会非常感激的

谢谢。

这应该可以做到:

@echo off
setlocal enabledelayedexpansion

cd /d D:\XYZ
for /f "tokens=*" %%a in ('dir /b /ad') do (
  if exist "%%a\%%a" (
    xcopy /E "%%a\%%a\*" "%%a"
    rd /s /q "%%a\%%a" 
  )
)

我要走PowerShell路线。这有两个选项,默认情况下它将删除任何双文件夹,因此…
Z:\XYZ\John Doe\John Doe\My Documents\Stuff\Stuff\ItsAFile.txt
变成:
Z:\XYZ\John Doe\My Documents\Stuff\ItsAFile.txt
如果您只想删除第一个重复的文件夹,请注释掉第6行,并取消注释第7行。如果您不喜欢报告部分,请删除/注释写输出行

$BasePath = "D:\XYZ"
gci $BasePath -recurse | %{
    $OriginalFile = $_
    If($OriginalFile.PSIsContainer){$FilePath = $_.FullName.ToString().Split('\')}
    Else{$FilePath = $_.Directory.ToString().Split('\')}
    for($i=1;$i -lt $FilePath.Count;$i++){    #Comment out this line to change to Base Path +2 folders method
#    for($i=0;$i -lt $($BasePath.Split('\').Count +2);$i++){    #Uncomment to only affect the first 2 folders past the base path
        if($filepath[$i] -and ($FilePath[$i] -ieq $FilePath[$i-1])){
            $FilePath[$i-1] = $Null
        }
    }
    ($FilePath|?{$_}) -join '\'|%{
        if($OriginalFile.PSIsContainer){
            If(!($OriginalFile.FullName -ieq $_)){
            Write-Output "Moving folder $($OriginalFile.fullname) to $_"
            move-item "$($OriginalFile.fullname)\*" $_ -ErrorAction SilentlyContinue
            Remove-Item $OriginalFile.fullname -ErrorAction SilentlyContinue}
        }else{
            If(!($OriginalFile.Directory.ToString() -ieq $_)){
            Write-Output "Moving file $($OriginalFile.fullname) to $(Resolve-Path "$_\..")"
            move-item $OriginalFile.fullname "$_\.." -ErrorAction SilentlyContinue
        }}
    }
}
要实现这一点,需要:

  • 提取基本路径中每个文件夹或文件的目录列表

  • 对于每一个,它根据反斜杠字符分割路径, 不包括文件名

  • 然后,它逐步通过每个段,将每个文件夹与一个文件夹进行比较 在路径中它之前(或仅步进前几段,如果需要 走那条路)

  • 如果两个连续文件夹匹配,则删除第一个文件夹

  • 然后在该过程结束时重建路径

  • 然后将修改后的路径与原始路径进行比较,如果 它们是不同的,它会将该项移动到修改后的路径


  • 它确实以不同的方式处理文件和文件夹,因为它使用文件夹的.FullName属性和文件的.Directory属性。

    所有有问题的文件夹都在D:\XYZ中吗?[对不起,我是StackOverflow新手,昨天才收到通知。]是的,所有文件夹都在D:\XYZ中。这非常有效。非常感谢你。至于@TheMadTechnician的另一个解决方案,我还没有尝试过。这更简单,对我的3000多个文件夹来说效果很好,但我还是感谢他的帮助。