파일이 하드 링크인지, 심볼릭 링크인지 확인하시겠습니까?

파일이 하드 링크인지, 심볼릭 링크인지 확인하시겠습니까?

파일의 파일 이름/경로를 가져와 파일이 심볼릭 링크인지 하드 링크인지 확인하는 쉘 스크립트를 만들고 있습니다.

유일한 문제는 그것이 하드 링크인지 확인하는 방법을 모른다는 것입니다. 테스트 파일로 사용하기 위해 하드 링크와 심볼릭 링크 등 2개의 파일을 만들었습니다. 하지만 파일이 하드 링크인지 아니면 쉘 스크립트의 기호인지 어떻게 알 수 있나요?

또한 심볼릭 링크의 대상 파티션을 어떻게 찾나요? 다른 파티션에 연결된 파일이 있다고 가정하면 해당 원본 파일의 경로를 어떻게 찾을 수 있습니까?

답변1

testJim의 답변에서는 의 테스트를 사용하여 심볼릭 링크를 테스트하는 방법을 설명합니다 -L.

그러나 엄밀히 말하면 "하드 링크"를 테스트하는 것은 원하는 것이 아닙니다. 하드 링크의 작동 방식은 Unix가 파일을 처리하는 방식에 따라 다릅니다. 각 파일은 inode로 표시됩니다. 그런 다음 단일 inode는 0개 이상의 값을 갖습니다.이름또는디렉토리 항목아니면 기술적으로 말하자면,하드 링크("문서"라고 부르는 것).

다행히도 이 stat명령(사용 가능한 경우)은 inode에 몇 개의 이름이 있는지 알려줄 수 있습니다.

따라서 다음과 같은 것을 찾고 있습니다(여기서 GNU 또는 busybox 구현을 가정 stat).

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

-c '%h'비트는 statinode에만 출력되는 하드 링크 수, 즉 파일 이름의 수를 나타냅니다. -gt 1그런 다음 1보다 큰지 확인하십시오.

다른 파일과 마찬가지로 심볼릭 링크도 여러 디렉터리에 연결될 수 있으므로 심볼릭 링크에 대한 하드 링크가 여러 개 있을 수 있습니다.

답변2

한 가지 예:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

f1, f2디렉토리 항목은 f3동일한 파일입니다(동일한 inode: 10802124, 알 수 있듯이링크예 3). 그들은 동일한 하드 링크입니다정기적인문서.

s4또한 s5동일한 파일(10802384)입니다. 그들은 유형에 속합니다심볼릭 링크, 아니요정기적인. 그들은 바로 여기의 길을 가리킵니다 s3. s4s5은 동일한 디렉터리에 있는 항목 이므로 s3두 항목의 상대 경로는 동일한 파일(inod 10802347의 파일)을 가리킵니다.

를 실행하는 경우 ls -Ll, 즉 심볼릭 링크를 해결한 후 파일 정보를 요청합니다.

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

당신은 그들 모두를 찾을 수 있습니다해결하다동일한 파일(10802124)에 추가합니다.

파일이 심볼릭 링크인지 확인할 수 있습니다 [ -L file ]. 마찬가지로 파일이 일반 파일인 경우 test를 사용할 수 있지만 [ -f file ]이 경우 심볼릭 링크가 해결된 후에 검사가 수행됩니다.

하드 링크는 파일 유형이 아니며 파일(모든 유형)의 다른 이름일 뿐입니다.

링크 수를 확인하여 파일이 하나 이상의 디렉토리에 다중(하드) 링크되어 있는지 확인할 수 있습니다.

POSIX적으로:

has_more_than_one_link() (
  export LC_ALL=C # only locale where the output of ls -n is specified
  export TZ=UTC0  # simplify the mtime field (which we don't need anyway)
                  # generation as an optimisation.
  unset -v IFS    # for default separator for read to include space and
                  # tab, the only 2 "blank" characters in the C/POSIX locale
  ls -nqd -- "$1" | {
    read -r ignore links ignore &&
      [ "$links" -gt 0 ]
  }
)

또는 다음을 사용하여 zsh:

has_more_than_one_link() () (($#)) $1(Nl+1)

함수 본문은 기본 본문이 (($#))(매개변수 수가 0보다 크면 true를 반환함) 익명 함수이고, 매개변수는 파일에 대한 링크 수가 1보다 큰 경우에만 $1(Nl+1)와일드카드 문자의 확장입니다. $1, 로 확장될 예정입니다.

또는 stat내장된 기능을 사용하세요:

zmodload zsh/stat
has_more_than_one_link() {
  stat -LA2 +nlink -- "$1" && (( $2 > 1 ))
}

$2( 별도의 변수를 선언할 필요가 없도록 링크 수를 저장합니다.현지의).

일부 시스템에는 외부 stat명령(보통 의 명령보다 이후 zsh)도 있지만 모두 서로 다른 인터페이스를 갖고 있습니다 zsh.

GNU 구현을 사용하면 특별히 호출된 파일 stat을 처리해야 합니다 . GNU는 이것을 -stdin에서 stat작업을 수행하는 것을 의미하는 것으로 해석하기 때문입니다.fstat()

has_more_than_one_link() {
  local nlink
  [ "$1" != - ] || set ./-
  nlink=$(stat -c %h -- "$1") &&
    [ "$nlink" -gt 1 ]
}

(이는 POSIX와 유사한 쉘이 local범위를 지원한다고 가정합니다).

답변3

명령의 -hAND 연산자를 사용하십시오.-Ltest

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

~에 따르면이 스레드, 동작은 동일하지만 -L선호됩니다.

답변4

여기에는 매우 정확한 답변이 많이 있지만 원래의 오해를 실제로 해결한 사람은 아무도 없다고 생각합니다. 원래 질문은 기본적으로 "심볼릭 링크를 만들면 나중에 식별하기 쉽습니다. 하지만 하드 링크를 식별하는 방법을 모르겠습니다."였습니다. 예, 대답은 기본적으로 "할 수 없습니다"로 귀결됩니다. 이하 그 이유를 설명하지만, 사실 그것이 혼란스럽고 이상하다는 사실을 누구도 인정하지 않는 것 같습니다.

이 모든 내용을 읽고 이미 무슨 일이 일어나고 있는지 알고 계시다면 제 글을 한 부분도 읽으실 필요가 없습니다. 여전히 혼란스럽다면 계속 진행하세요.

아주 짧은 대답은 하드 링크는 심볼릭 링크와 달리 실제로 링크가 아니라는 것입니다. 이는 원래 디렉토리 항목과 동일한 바이트 문자열을 가리키는 디렉토리 구조의 새 항목이며 일단 생성되면 첫 번째 항목과 마찬가지로 "실제"이고 합법적입니다.모든드라이브의 "일반" 파일에는 하드 링크가 하나 이상 있으며 이를 볼 수 없습니다.어느디렉터리이므로 참조하거나 사용할 수 없습니다. 따라서 Fred.txt 파일이 있고 Wilma.txt 및 Barney.txt를 해당 파일에 하드 링크하는 경우 세 가지 이름(및 디렉터리 항목)은 모두 동일한 파일을 참조하며 모두 동일하게 유효합니다. 운영 체제는 텍스트 편집기에서 "저장"을 클릭했을 때 항목 중 하나가 생성된 반면 다른 항목은 "ln" 명령을 사용하여 생성되었음을 알 수 없습니다.

운영 체제하다그러나 동일한 파일을 가리키는 서로 다른 항목 수를 추적해야 합니다. Wilma.txt를 삭제해도 드라이브 공간이 확보되지 않는다는 것은 놀라운 일이 아닙니다. 그러나 Fred.txt("원본" 파일)를 삭제해도 드라이브의 Fred.txt라는 데이터는 여전히 Barney.txt이므로 드라이브의 공간을 확보할 수 없습니다. 삭제하는 경우에만모두디렉토리 항목의 수로 인해 운영 체제는 데이터 자체가 차지하는 공간을 할당 해제합니다.

Barney.txt가 심볼릭 링크인 경우 Fred.txt를 삭제하세요.회의공간 할당이 취소되었으며 Barney.txt는 이제 끊어진 링크가 됩니다. 또한 심볼릭 링크가 가리키는 파일을 이동하거나 이름을 바꾸면 링크가 끊어집니다. 그러나 하드 링크 파일은 해당 파일/데이터를 가리키는 다른 디렉토리 항목을 손상시키지 않고 마음대로 이동하거나 이름을 바꿀 수 있습니다. 왜냐하면 해당 파일/데이터는 모두 드라이브의 동일한 데이터 블록을 참조하는 디렉토리 항목이기 때문입니다(해당 데이터의 inode 번호 사용). .

[2년 후, 마지막엔 조금 혼란스러워잠깐만요. 명확히 해야겠다고 생각했어요. "mv ./Wilma.txt ../elsewhere/Betty.txt"를 입력하면 파일을 이동하는 것처럼 보이지만 실제로는 그렇지 않습니다. 실제로 수행하고 있는 작업은 현재 디렉터리에 대한 디렉터리 목록에서 "'Wilma.txt'라는 이름은 inode ######" #을 사용하여 찾을 수 있는 데이터와 연결되어 있습니다"라는 줄 항목을 제거하고 보고하는 것입니다. ../elsewhere 디렉토리의 디렉토리 목록에 "'Betty.txt'라는 이름은 inode #######을 통해 발견된 데이터와 연결되어 있습니다"라는 새 줄 항목을 추가합니다. 이것이 바로 2처럼 이동할 수 있는 이유입니다. KB 파일을 동일한 드라이브의 다른 위치로 최대한 빨리 이동할 수 있습니다.

운영 체제는 동일한 데이터 블록을 가리키는 서로 다른 디렉토리 항목 수를 추적해야 하기 때문에할 수 있는보고 있는 디렉토리 항목이 "원래" 디렉토리 항목인지 확신할 수 없는 경우에도 특정 파일이 하드 링크되어 있는지 확인하십시오. 한 가지 방법은 "ls" 명령, 특히 "ls -l"(즉, 대시 뒤의 소문자 L)입니다.

이전 예를 빌려서...

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

첫 번째 문자는 대시이므로 디렉토리나 이상한 것이 아니며 "일반" 일반 파일입니다. 그러나 그것이 정말로 평범하다면, "이 데이터 블록을 가리키는 디렉토리 항목이 있습니다"에서와 같이 rwx-ish 부분 뒤의 숫자는 "1"이 될 것입니다. 그러나 이는 하드 링크 데모의 일부이므로 "3"으로 표시됩니다.

이로 인해 이상하고 신비한 동작이 발생할 수 있습니다(하드 링크를 심각하게 받아들이지 않는 경우). 텍스트 편집기에서 Fred.txt를 열고 몇 가지 사항을 변경하면 Wilma.txt와 Barney.txt에서도 동일한 변경 사항이 표시됩니까? 아마도. 아마도. 텍스트 편집기가 원본 파일을 열고 변경 사항을 기록하여 변경 사항을 저장하는 경우 세 이름 모두 여전히 동일한(새로 변경된) 텍스트를 가리킵니다. 그러나 텍스트 편집기가 새 파일(Fred-new-temp.txt)을 생성하고 변경된 버전을 해당 파일에 쓴 다음 Fred.txt를 삭제하고 Fred-new-temp.txt의 이름을 Fred.txt로 바꾸면 Wilma 및 Barney는 새로 변경된 버전이 아닌 원래 버전을 가리킵니다. 하드 링크를 이해하지 못한다면 약간 화를 낼 수도 있습니다. :) [글쎄요, 저는 개인적으로 사실 하나도 모릅니다.텍스트 에디터이것은 새 파일/이름 바꾸기 작업을 수행하지만 정확히 그 작업을 수행하는 다른 프로그램을 많이 알고 있으므로 주의하십시오. ]

마지막 참고 사항: "fsck"(파일 시스템 검사)가 확인하는 작업 중 하나는 일부 디렉터리 항목에서 더 이상 참조하지 않는 데이터 블록이 드라이브에 있는지 여부입니다. inode를 가리키는 고유 디렉토리 항목이 삭제되지만 드라이브 공간 자체가 "사용 가능"으로 표시되지 않는 경우 문제가 발생하는 경우가 있습니다. 따라서 fsck의 작업 중 하나는 할당된 모든 공간을 모든 디렉터리 항목과 일치시켜 참조되지 않은 파일이 없는지 확인하는 것입니다. 일부를 찾으면 새 디렉토리 항목을 생성하고 "lost+found"에 넣습니다.

관련 정보