어쨌든, 우리의 오래된 Server 2008 (R2 아님) 상자 중 하나는 무한히 반복되는 폴더를 개발했습니다. 백업 에이전트가 폴더로 재귀를 시도하고 다시는 돌아 오지 않기 때문에 백업과 함께 작동합니다.
폴더 구조는 다음과 같습니다.
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가 충돌하기 전에 몇 분 동안 폴더를 회전합니다.
누구나이 폴더를 잘 제거하는 방법을 제안 할 수 있습니까?
답변
유용한 조언을 주신 모든 분들께 감사드립니다.
StackOverflow 영역에 잘 들어가서이 C # 코드 스 니펫을 두드려 문제를 해결했습니다. 긴 파일 경로에 액세스하는 문제를 구체적으로 해결 하는 Delimon.Win32.IO 라이브러리를 사용합니다 .
이것이 다른 누군가를 도울 수있는 경우를 대비하여 여기에 코드가 있습니다. 어쨌든 붙어있는 ~ 1600 레벨의 재귀를 통과했으며 모두 제거하는 데 약 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--;
}
}
}
답변
재귀 연결 지점이 될 수 있습니다. 이러한 것은 Sysinternalsjunction
의 파일 및 디스크 유틸리티를 사용 하여 만들 수 있습니다 .
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 유틸리티를 삭제하려면 다음을 수행하십시오.
junction -d c:\Hello\Hello
답변
답이 아니지만 의견을 제출할 충분한 담당자가 없습니다.
한 번 MS-DOS 시스템의 거대한 500MB FAT16 디스크에서이 문제를 해결했습니다. DOS 디버그를 사용하여 디렉토리 테이블을 수동으로 덤프하고 구문 분석했습니다. 그런 다음 재귀 디렉토리를 삭제 된 것으로 표시하기 위해 1 비트를 뒤집 었습니다. Dettman과 Wyatt ‘DOS Programmers’Reference ‘의 사본은 저에게 길을 보여주었습니다.
나는 여전히 이것을 자랑스럽게 생각합니다. FAT32 또는 NTFS 볼륨보다 강력한 기능을 갖춘 범용 도구가 있다면 놀랍습니다. 그 당시의 삶은 더 단순했습니다.
답변
Java는 긴 파일 경로를 처리 할 수도 있습니다. 그리고 훨씬 더 빨리 할 수 있습니다. 이 코드 (Java API 문서에서 복사 한)는 약 1 초 (Windows 7, Java 8.0에서)에서 1600 수준의 딥 디렉토리 구조를 삭제하며 실제로 재귀를 사용하지 않기 때문에 스택 오버플로의 위험이 없습니다.
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"));
}
}
답변
chdir
디렉토리에 들어가고 상대 경로를 사용하는 경우 긴 경로 이름이 필요하지 않습니다 rmdir
.
또는 POSIX 셸이 설치되어 있거나 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
루프 조건에서 쉘 변수를 사용하여 이름을 바꾼 위치를 추적하는 것은 내가했던 것처럼 루프를 풀 때의 다른 대안입니다.
이렇게하면 KenD 솔루션의 CPU 오버 헤드를 피할 수 있습니다. 이로 인해 OS n
는 새 수준이 추가 될 때마다 트리를 최상위에서 최상위 수준으로 이동하고 권한 등을 확인하므로 sum(1, n) = n * (n-1) / 2 = O(n^2)
시간이 복잡합니다. 체인의 시작 부분에서 청크를 제거하는 솔루션 O(n)
은 부모 디렉토리의 이름을 바꿀 때 Windows가 트리를 통과 해야하는 경우 가 아니면 안됩니다 . (Linux / Unix는 그렇지 않습니다.) OS가 모든 것을 검사 할 필요가 없다고 가정 할 때 chdir
트리의 맨 아래까지 내려 가면서 경로를 chdir
백업하고 디렉토리를 제거하는 솔루션 도 있어야 O(n)
합니다. CD가있는 동안 작업을 수행 할 때 모든 시스템 호출마다 상위 디렉토리.
find Folder1 -depth -execdir rmdir {} +
CD가 가장 깊은 디렉토리에있는 동안 rmdir을 실행합니다. 또는 실제로 find의 -delete
옵션은 디렉토리에서 작동하며을 의미합니다 -depth
. 그래서 find Folder1 -delete
똑같은 일을하지만, 빨리해야한다. 그래, 리눅스에서 GNU의 발견은 다음 상대 경로와 하위 디렉토리에있는 디렉토리, CDing를 스캔하여 하강 rmdir
한 후, 상대 경로로 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 1 세대 Core2Duo CPU, WD 2.5TB Green Power drive (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는 디렉토리 및 누락 된 경로 구성 요소를 작성합니다).
2k rmdir ops의 경우 실제로 0.05 초입니다. xfs는 메타 데이터 작업을 10 년 전과 같이 느리게 수정했기 때문에 저널에서 메타 데이터 작업을 일괄 처리하는 데 매우 능숙합니다.
ext4에서 create는 0m0.279s가었고 find는 여전히 0m0.074s가되었습니다.
답변
일부 Java 응용 프로그램에서했던 5000+ 디렉토리 깊이의 폴더 엉망과 같은 문제가 발생 했으며이 폴더를 제거하는 데 도움이되는 프로그램을 작성했습니다. 전체 소스 코드는 다음 링크에 있습니다.
https://imanolbarba.net/gitlab/imanol/DiREKT
그것은 잠시 후에 모든 것을 제거했지만 일을 처리했습니다. 나는 그것이 같은 좌절감을 느끼는 사람들에게 도움이되기를 바랍니다.
답변
나도 이것을 독립형 Windows 10 시스템에서 가지고있었습니다. C : \ User \ Name \ Repeat \ Repeat \ Repeat \ Repeat \ Repeat \ Repeat \ Repeat가 무한대로 보입니다.
Windows 또는 명령 프롬프트를 사용하여 약 50 번째까지 탐색 할 수 있습니다. 삭제하거나 클릭 할 수 없습니다.
C는 내 언어이므로 결국 시스템 호출 루프가있는 프로그램을 작성하여 실패 할 때까지 반복합니다. DOS 배치에서도 모든 언어 로이 작업을 수행 할 수 있습니다. 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 개였습니다. 그 원인을 알 수 없습니다. 미친.