不知何故,我们之前的Server 2008(不是R2)盒子已经开发了一个看似无限recursion的文件夹。 这是与我们的备份玩破解,因为备份代理试图递减到文件夹,永远不会返回。
文件夹结构如下所示:
C:\Storage\Folder1 C:\Storage\Folder1\Folder1 C:\Storage\Folder1\Folder1\Folder1 C:\Storage\Folder1\Folder1\Folder1\Folder1
… 等等。 这就像90年代我们曾经玩过的Mandelbrot套装中的一个。
我试过了:
RMDIR C:\Storage\Folder1 /Q/S
– 这个返回The directory is not empty
ROBOCOPY C:\temp\EmptyDirectory C:\Storage\Folder1 /PURGE
– 在robocopy.exe崩溃之前,这将在文件夹中旋转几分钟。 任何人都可以build议一种方法来杀死这个文件夹好?
感谢大家提供有用的build议。
进入StackOverflow领域,我已经解决了这个C#代码片段的问题。 它使用Delimon.Win32.IO库专门解决访问长文件path的问题。
以防万一这可以帮助别人,这里的代码 – 它通过〜1600级别的recursion,我不知怎么卡住了,花了大约20分钟,将其全部删除。
using System; using Delimon.Win32.IO; namespace ConsoleApplication1 { class Program { private static int level; static void Main(string[] args) { // Call the method to delete the directory structure RecursiveDelete(new DirectoryInfo(@"\\server\\c$\\storage\\folder1")); } // This deletes a particular folder, and recurses back to itself if it finds any subfolders public static void RecursiveDelete(DirectoryInfo Dir) { level++; Console.WriteLine("Now at level " +level); if (!Dir.Exists) return; // In any subdirectory ... foreach (var dir in Dir.GetDirectories()) { // Call this method again, starting at the subdirectory RecursiveDelete(dir); } // Finally, delete the directory, and any files below it Dir.Delete(true); Console.WriteLine("Deleting directory at level " + level); level--; } } }
可能是一个recursion交接点。 这样的事情可以用Sysinternals的文件和磁盘实用程序创build。
mkdir c:\Hello junction c:\Hello\Hello c:\Hello
你现在可以无休止地下去c:\ Hello \ Hello \ Hello ….(直到达到MAX_PATH,大多数命令为260个字符,而某些Windows API函数为32,767个字符)。
目录列表显示它是一个连接点:
C:\>dir c:\hello Volume in drive C is DR1 Volume Serial Number is 993E-B99C Directory of c:\hello 12/02/2015 08:18 AM <DIR> . 12/02/2015 08:18 AM <DIR> .. 12/02/2015 08:18 AM <JUNCTION> hello [\??\c:\hello] 0 File(s) 0 bytes 3 Dir(s) 461,591,506,944 bytes free C:\>
要删除使用连接实用程序:
junction -dc:\Hello\Hello
不是一个答案,但我没有足够的代表评论。
我曾经在MS-DOS系统上的一个庞大的500MB FAT16光盘上解决了这个问题。 我使用DOSdebugging手动转储和parsing通过目录表。 然后我翻转了一下,将recursion目录标记为已删除。 我的Dettman和Wyatt'DOS程序员参考'的副本给我指明了方向。
我仍然为此感到自豪。 如果有任何通用工具具有超过FAT32或NTFS卷的能力,我会感到惊讶和恐惧。 当时的生活比较简单。
Java也可以处理长文件path。 它也可以做得更快。 这段代码(我从Java API文档中复制而来)将在大约1秒(Windows 7,Java 8.0)下删除一个1600级深度的目录结构,并且没有堆栈溢出的风险,因为它实际上并没有使用recursion。
import java.nio.file.*; import java.nio.file.attribute.*; import java.io.*; public class DeleteDir { static void deleteDirRecur(Path dir) throws IOException { Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { Files.delete(dir); return FileVisitResult.CONTINUE; } else { throw e; } } }); } public static void main(String[] args) throws IOException { deleteDirRecur(Paths.get("C:/Storage/Folder1")); } }
如果您进入目录并使用rmdir
相对path,则不需要长path名。
或者,如果您安装了POSIXshell程序,或将其移植到与DOS相同的程序:
# untested code, didn't bother actually testing since the OP already solved the problem. while [ -d Folder1 ]; do mv Folder1/Folder1/Folder1/Folder1 tmp # repeat more times to work in larger batches rm -r Folder1 # remove the first several levels remaining after moving the main tree out # then repeat to end up with the remaining big tree under the original name mv tmp/Folder1/Folder1/.../Folder1 Folder1 rm -r tmp done
(使用shellvariables来跟踪你为循环条件重命名的地方是展开循环的另一种方法,就像我在那里做的那样)。
这样可以避免KenD解决scheme的CPU开销,每次添加一个新的级别,检查权限等,强制操作系统从顶层到第n
级遍历树,因此它有sum(1, n) = n * (n-1) / 2 = O(n^2)
时间复杂度。 从链的开头剥离块的解决scheme应该是O(n)
,除非Windows在重命名其父目录时需要遍历树。 (Linux / Unix没有。)解决schemechdir
一直到树的底部,并使用相对path,当他们chdir
备份时删除目录,也应该是O(n)
,假设操作系统不'你需要在每个系统调用时检查你所有的父目录,当你在CD的某个地方做事时。
find Folder1 -depth -execdir rmdir {} +
将运行rmdir而CDed到最深的目录。 或者实际上,find的-delete
选项在目录上工作,并暗示-depth
。 所以find Folder1 -delete
应该做同样的事情,但更快。 是的,GNU在Linux上查找通过扫描目录,CDing到相对path的子目录,然后rmdir
与相对path,然后chdir("..")
。 它不升级时重新扫描目录,所以会消耗O(n)
RAM。
这真是一个近似值: strace
显示它实际上使用unlinkat(AT_FDCWD, "tmp", AT_REMOVEDIR)
, open("..", O_DIRECTORY|...)
和fchdir(the fd from opening the directory)
fstat
电话也混入了。 但是,如果目录树在find运行时没有被修改,效果是一样的。
编辑:只是踢,我在GNU / Linux上(Ubuntu 14.10,在2.4GHz第一代Core2Duo CPU上,在WD 2.5TB绿色电源驱动器(WD25EZRS)上的XFS文件系统上)尝试了这个。
time mkdir -p $(perl -e 'print "annoyingfoldername/" x 2000, "\n"') real 0m1.141s user 0m0.005s sys 0m0.052s find annoyingfoldername/ | wc 2000 2000 38019001 # 2k lines / 2k words / 38M characters of text ll -R annoyingfoldername ... eventually ls: cannot access ./annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername: File name too long total 0 ?????????? ? ? ? ? ? annoyingfoldername time find annoyingfoldername -delete real 0m0.054s user 0m0.004s sys 0m0.049s # about the same for normal rm -r, # which also didn't fail due to long path names
(mkdir -p创build一个目录和任何缺less的path组件)。
是的,对于2k rmdir操作,真的是0.05秒。 xfs在日志中对元数据操作进行批处理是相当不错的,因为它们修复了像10年前那样慢的元数据操作。
在ext4上,创build了0m0.279s,用find删除仍然花费了0m0.074s。
我遇到了5000多个目录深层的文件夹混乱,一些Java应用程序,我写了一个程序,将帮助您删除此文件夹相同的问题。 整个源代码在这个链接:
https://imanolbarba.net/gitlab/imanol/DiREKT
一段时间之后,它把整件事情都清除了,但是它设法做好了这个工作,我希望它能帮助那些(和我一样)遇到同样令人沮丧的问题的人
不过,我也是在独立的Windows 10系统上这样做的。 C:\用户名\重复\重复\重复\重复\重复\重复\重复看似无穷。
我可以使用Windows或命令提示符导航到大约第50个,而且没有更多。 我无法删除它,或点击它等。
C是我的语言,所以最终我编写了一个系统调用循环的程序,这个循环直到失败。 你可以用任何语言做到这一点,甚至DOS批处理。 我创build了一个名为tmp的目录,并将Repeat \ Repeat移动到该目录中,删除了现在为空的Repeat文件夹,并将tmp \ Repeat移回到当前文件夹中。 一遍又一遍地!
while (times<2000) { ChkSystem("move Repeat\\Repeat tmp"); ChkSystem("rd Repeat"); ChkSystem("move tmp\\Repeat Repeat"); ++times; printf("Removed %d nested so far.\n", times); }
ChkSystem只是运行一个system()调用并检查返回值,如果失败则停止。
重要的是,它失败了很多次。 我想可能是我的程序没有工作,或者这个程序毕竟是无限的。 但是,之前我曾经有过系统调用,但事情并没有同步,所以我只是再次运行这个程序,并从停止的地方继续运行,所以不要马上认为你的程序没有工作。 所以总共运行了大约20次后,全部清除了。 总共是1280个文件夹。 不知道是什么造成的。 疯。