rm my-symlink와 rm my-symlink/의 차이점

rm my-symlink와 rm my-symlink/의 차이점

rm -rf my-symlink이 기능을 사용하면 심볼릭 링크만 삭제되고 rm -rf my-symlink/링크된 디렉터리 내의 파일은 삭제되고 심볼릭 링크는 그대로 유지되는 이유를 알고 싶었습니다 .

답변1

stat my-symlink와 의 출력을 비교하면 차이점을 확인할 수 있습니다 stat my-symlink/. my-symlink, 슬래시가 없으면 기호 링크 자체입니다. my-symlink/슬래시가 있는 은 심볼릭 링크가 가리키는 디렉터리이며, 이 my-symlink/디렉터리가 가리키는 디렉터리의 inode를 비교하여 별도로 확인할 수 있습니다.

해당 정보를 사용하면 보고 있는 동작이 에 설명된 것과 일치합니다.rm님의 사양: 심볼릭 링크를 처리할 때 rm링크가 디렉토리를 가리키는 경우 "들어가"지 않고 링크를 삭제합니다. 옵션을 사용하여 디렉터리를 처리할 때 -r해당 내용을 재귀적으로 삭제합니다. 이 my-symlink/경우 에는 rm"디렉토리"를 삭제하려고 시도하지만 디렉토리가 아니라 심볼릭 링크이기 때문에 실패합니다. 그러나 플래그 때문에 -f오류가 발생하지 않습니다.

답변2

나는 그 행동을 조금 더 조사해야겠다고 생각했기 때문에 여기에 또 다른 대답이 있습니다.

내부적으로 rmFTS파일 계층 구조로 재귀적으로 사용합니다. fts_open경로 배열을 매개변수로 사용하고 각 경로에 대한 트리 구조를 생성합니다. 이를 통해 프로그래머는 마치 하나의 통합 계층 구조의 일부인 것처럼 여러 위치를 겉보기에 탐색할 수 있습니다.

다음은 FTS를 직접 플레이하는 데 사용할 수 있는 테스트 프로그램입니다.

#include <stdio.h>
#include <stdlib.h>
#include <fts.h>

int main(int argc, char* argv[])
{
    if(argc < 2) return EXIT_FAILURE;

    char* const* arr = argv + 1;
    FTS* hier = fts_open(arr, FTS_NOSTAT | FTS_PHYSICAL, NULL);

    FTSENT* ent;
    while((ent = fts_read(hier))) {
        printf("%s info=%d (D=%d DP=%d F=%d SL=%d)\n",
               ent->fts_accpath, ent->fts_info,
               ent->fts_info == FTS_D, ent->fts_info == FTS_DP,
               ent->fts_info == FTS_F || ent->fts_info == FTS_NSOK,
               ent->fts_info == FTS_SL);
    }

    fts_close(hier);
    return EXIT_SUCCESS;
}

다음과 같은 디렉터리 구조를 생성했다고 가정해 보겠습니다.

$ mkdir dir
$ touch dir/file
$ ln -s dir sym

이제 첫 번째 사례를 고려하여 FTS가 탐색을 어떻게 주도하는지 살펴보겠습니다.

$ gcc fts.c 
$ ./a.out sym
sym info=12 (D=0 DP=0 F=0 SL=1)

보시다시피 이 경우에는 sym파일로 표시됩니다. 더 정확하게 말하면 심볼릭 링크입니다. 따라서 이 정보를 사용하여 rm에서는 이를 파일로 처리하고 를 호출합니다 unlinkat(AT_FDCWD, "sym", 0). 마지막 매개변수(0)는 다음 unlinkat과 같이 동작합니다 unlink. 즉, 단순히 파일을 삭제합니다. 결과적으로 링크가 사라집니다.

이제 에서 무슨 일이 일어나는지 살펴보겠습니다 sym/.

$ ./a.out sym/
sym/ info=1 (D=1 DP=0 F=0 SL=0)
file info=11 (D=0 DP=0 F=1 SL=0)
sym/ info=6 (D=0 DP=1 F=0 SL=0)

이 경우에는 sym대상 디렉터리로 처리되었습니다. 먼저 까지 반복 sym한 다음 sym/file다시 반복합니다 sym. 마지막 것은 FTS의 작동 방식 때문입니다. 먼저 내용을 반복한 다음 루트 노드로 돌아옵니다. 이것은 실제로 매우 편리합니다 rm. 첫 번째 단계( D)에서는 파일을 지울 수 있고 두 번째 단계( DP)에서는 빈 디렉터리를 제거할 수 있습니다.

보시다시피, 이 경우 FTS는 sym/두 경우 모두 디렉터리로 보고합니다. 이는 커널이 해당 경로를 디렉토리로 해석하도록 하기 위해 뒤에 슬래시를 붙여 경로를 제공했기 때문입니다. 링크의 경우 이는 무슨 일이 있어도 링크를 따라갈 것임을 의미합니다.보다 기술적인 용어로 사양에 따르면 다음과 같습니다.

하나 이상의 슬래시가 아닌 문자를 포함하고 하나 이상의 후행 슬래시로 끝나는 경로 이름은 단일 점 문자( '.' )가 경로 이름에 추가된 것처럼 해석됩니다.

sym/FTS는 디렉터리로 보고하기 때문에 rm마치 빈 디렉터리를 삭제하는 것처럼 동작합니다. 이에 따라 unlinkat(AT_FDCWD, "sym/", AT_REMOVEDIR). unlinkat이로 인해 rmdir.

그러나 sym/경로 를 확인하면 unlinkat시스템 호출은 실제로 디렉터리가 제공되지 않는다는 것을 깨닫게 됩니다. 따라서 보고서는 ENOTDIR다음을 트리거합니다.

$ rm: cannot remove ‘sym/’: Not a directory

-f그리고 실제로 통화에서 플래그를 제거하면 ... 그것이 바로 여러분이 보게 될 것입니다. 자, 이것이 버그인지 기능인지... 잘 모르겠습니다.

관련 정보