부적절한 순간 에이 문제에 대해 몇 번 나왔습니다.
- 딥 패스로 오픈 소스 Java 프로젝트 작업
- 소스 제어에 Deep Fitnesse 위키 트리 저장
- Bazaar를 사용하여 소스 제어 트리를 가져 오는 중에 오류가 발생했습니다.
이 한계가 존재하는 이유는 무엇입니까?
왜 아직 제거되지 않았습니까?
경로 제한에 어떻게 대처합니까? 그리고 아니요, Linux 또는 Mac OS X로 전환하는 것이이 질문에 대한 올바른 대답은 아닙니다.)
답변
이 기사 인용하기 https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
최대 경로 길이 제한
Windows API에서 (다음 단락에서 설명하는 일부 예외) 경로의 최대 길이는 MAX_PATH 이며 260 자로 정의됩니다. 로컬 경로는 드라이브 문자, 콜론, 백 슬래시, 백 슬래시로 구분 된 이름 구성 요소 및 종료 널 문자의 순서로 구성됩니다. 예를 들어, 드라이브 D의 최대 경로는 “D : \ some 256 자 경로 문자열 <NUL>”입니다. 여기서 “<NUL>”은 현재 시스템 코드 페이지의 보이지 않는 종료 널 문자를 나타냅니다. (<> 문자는 시각적 선명도를 위해 사용되며 유효한 경로 문자열의 일부가 될 수 없습니다.)
이제 우리는 그것이 1 + 2 + 256 + 1 또는 [drive] [: \] [path] [null] = 260임을 알 수 있습니다. 256은 DOS 시절의 적당한 고정 문자열 길이라고 가정 할 수 있습니다. DOS API로 돌아가서 시스템이 드라이브 당 현재 경로를 추적했으며 최대 드라이브 수 (및 현재 디렉토리) 가 26 개 (기호가있는 32 개 ) 인 것을 알 수 있습니다.
INT 0x21 AH = 0x47은 “이 함수는 드라이브 문자와 초기 백 슬래시없이 경로 설명을 반환합니다.”라고 말합니다. 따라서 시스템이 CWD를 쌍 (드라이브, 경로)으로 저장하고 드라이브를 지정하여 경로를 요청한다는 것을 알 수 있습니다 (1 = A, 2 = B,…). 0을 지정하면 경로를 가정합니다. INT 0x21 AH = 0x15 AL = 0x19에 의해 반환 된 드라이브. 이제 4 바이트가 경로 문자열에 저장되지 않기 때문에 256이 아닌 260 인 이유를 알 수 있습니다.
640K가 충분한 RAM이기 때문에 256 바이트 경로 문자열이 필요한 이유는 무엇입니까?
답변
NTFS 파일 시스템이 최대 32k 문자의 경로를 지원하기 때문에 이것은 사실이 아닙니다. win32 api 및 ” \\?\
“접두어를 사용하여 260자를 초과하는 경로를 사용할 수 있습니다.
.Net BCL 팀 블로그 에서 긴 경로에 대한 자세한 설명 .
작은 발췌문은 긴 경로의 문제를 강조합니다.
또 다른 문제는 긴 경로 지원을 제공함으로써 발생하는 일관되지 않은 동작입니다.
\\?\
접두사가있는 긴 경로 는 대부분의 파일 관련 Windows API에서 사용할 수 있지만 일부 Windows API에서는 사용할 수 없습니다. 예를 들어, 파일 이름이 MAX_PATH보다 길면 모듈을 호출 프로세스의 주소에 매핑하는 LoadLibrary가 실패합니다. 따라서 MoveFile을 사용하면 경로가 260자를 초과하는 위치로 DLL을 이동할 수 있지만 DLL을로드하려고하면 실패합니다. Windows API 전체에 유사한 예제가 있습니다. 일부 해결 방법이 있지만 상황에 따라 다릅니다.
답변
문제는 여전히 제한이 존재하는 이유 입니다. 확실히 현대 Windows는 MAX_PATH
더 긴 경로를 허용하기 위해 측면을 늘릴 수 있습니다 . 제한이 제거되지 않은 이유는 무엇입니까?
- 제거 할 수없는 이유는 Windows가 절대 변경되지 않을 것이라고 약속했기 때문입니다.
API 계약을 통해 Windows는 표준 파일 API가 260
문자 보다 긴 경로를 반환하지 않도록 모든 응용 프로그램을 보장했습니다 .
다음 올바른 코드를 고려하십시오 .
WIN32_FIND_DATA findData;
FindFirstFile("C:\Contoso\*", ref findData);
Windows 는 내 프로그램이 내 WIN32_FIND_DATA
구조를 채우도록 보증 했습니다 .
WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
//...
TCHAR cFileName[MAX_PATH];
//..
}
내 응용 프로그램은 constant의 값을 선언 MAX_PATH
하지 않았으며 Windows API는 그랬습니다. 내 응용 프로그램은 그 정의 된 값을 사용했습니다.
내 구조가 올바르게 정의되었으며 592
총 바이트 수만 할당 합니다. 즉, 260
문자 보다 작은 파일 이름 만받을 수 있습니다. Windows 는 응용 프로그램을 올바르게 작성하면 앞으로도 계속 응용 프로그램이 작동 할 것이라고 약속했습니다.
Windows가 260
문자 보다 긴 파일 이름을 허용하는 경우 기존 응용 프로그램 (올바른 API를 올바르게 사용)이 실패합니다.
Microsoft가 MAX_PATH
상수 를 변경하도록 요구하는 사람은 먼저 기존 응용 프로그램이 실패하지 않도록해야합니다. 예를 들어, 나는 여전히 Windows 3.11에서 실행되도록 작성된 Windows 응용 프로그램을 소유하고 사용합니다. 여전히 64 비트 Windows 10에서 실행됩니다. 이것이 이전 버전과의 호환성을 제공합니다.
Microsoft 는 전체 32,768 경로 이름을 사용하는 방법을 만들었습니다. 그러나 그들은 그것을하기 위해 새로운 API 계약을 만들어야했습니다. 우선, 셸 API 를 사용하여 파일을 열거해야합니다 (모든 파일이 하드 드라이브 나 네트워크 공유에있는 것은 아님).
그러나 기존 사용자 응용 프로그램을 중단하지 않아도됩니다. 대부분의 응용 프로그램은 파일 작업에 쉘 API를 사용 하지 않습니다 . 모든 사람은 호출 FindFirstFile
/ FindNextFile
하루를 호출합니다.
답변
Windows 10에서 . 레지스트리 키를 수정 하여 제한 을 제거 할 수 있습니다 .
팁 Windows 10 버전 1607부터 일반적인 Win32 파일 및 디렉토리 기능에서 MAX_PATH 제한이 제거되었습니다. 그러나 새 동작을 선택해야합니다.
레지스트리 키를 사용하면 새로운 긴 경로 동작을 활성화하거나 비활성화 할 수 있습니다. 긴 경로 동작을 사용하려면 레지스트리 키를
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled
(유형 :)로 설정하십시오REG_DWORD
. 키 값은 영향을받는 Win32 파일 또는 디렉토리 기능을 처음 호출 한 후 시스템 (프로세스 당)에 의해 캐시됩니다 (목록은 다음과 같습니다). 프로세스 수명 동안 레지스트리 키가 다시로드되지 않습니다. 시스템의 모든 앱이 키 값을 인식하려면 키를 설정하기 전에 일부 프로세스가 시작되었을 수 있으므로 재부팅이 필요할 수 있습니다. 레지스트리 키는에서 그룹 정책을 통해 제어 할 수도 있습니다Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths
. 매니페스트를 통해 앱마다 새로운 긴 경로 동작을 활성화 할 수도 있습니다.<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application>
답변
폴더를 드라이브로 마운트 할 수 있습니다. 명령 행에서 경로가있는 경우 다음을 사용하여 경로 C:\path\to\long\folder
를 드라이브 문자에 맵핑 할 수 있습니다 X:
.
subst x: \path\to\long\folder
답변
경로 제한에 대처하는 한 가지 방법은 기호 링크로 경로 항목을 줄이는 것입니다.
예를 들면 다음과 같습니다.
C:\p
긴 경로에 대한 짧은 링크를 유지하기 위한 디렉토리를 만듭니다.mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
C:\p\foo
긴 경로 대신 경로에 추가