cp를 사용하여 소프트 링크를 하드 링크로 변환

cp를 사용하여 소프트 링크를 하드 링크로 변환

명령 cp페이지는 다음 info옵션을 제공합니다.--preserve=

links
대상 파일의 해당 소스 파일 간의 링크를 유지합니다. 알아채다-H'를 사용하면 -L' or이 옵션은할 수 있는심볼릭 링크를 하드 링크로 변환.

다음은 어쨌든 지금은 이해할 수 없는 예입니다.

질문: 소프트 링크를 하드 링크로 변환하는 방법은 무엇입니까 cp? [하드 링크를 소프트 링크로 변환] 방법이 있나요?


사소한 문제: 어디할 수 있는위의 인용문에서 역할을 합니까? 나는 -L목적을 이해하고 -H완전한 기능을 갖춘 소프트 링크 등을 복사할 수 있지만 지금까지 소프트 링크를 하드 링크로 전환하지 못했습니다.

답변1

정보 페이지의 예는 이 예가 따라가기가 약간 어렵다는 것을 보여줍니다.

$ mkdir c; : > a; ln -s a b; cp -aH a b c; ls -i1 c
74161745 a
74161745 b

이를 구성 요소 명령으로 분류해 보겠습니다.

  • mkdir c;: 디렉토리 생성c/
  • : > a;: 빈 파일을 만드는 빠른 방법입니다. 는 아무것도 하지 않는 bash 내장 과 동일합니다. 를 참조 echo "" > a하세요 .:help :
  • ln -s a ba: 통화 할 수 있는 소프트 링크를 만듭니다 b. 이때 현재 디렉터리의 내용은 다음과 같습니다.

    $ ls -l | cc2ter 
    total 4
    -rw-r--r-- 1 terdon terdon    0 Oct  9 02:50 a
    lrwxrwxrwx 1 terdon terdon    1 Oct  9 02:50 b -> a
    drwxr-xr-x 2 terdon terdon 4096 Oct  9 02:50 c
    

    이것은 b기호 링크(소프트 링크)이며 다음과 동일한 inode를 가리키지 않습니다 a.

    $ ls -i1c a b
    16647344 a
    16647362 b
    
  • cp -aH a b c;: 파일을 디렉토리 a에 복사합니다 . 여기에서 변환이 발생하며 전달되는 옵션은 다음과 같습니다.bccp

    -a, --archive
          same as -dR --preserve=all
    -d    same as --no-dereference --preserve=links
    -H    follow command-line symbolic links in SOURCE
    

    이는 -H(에서) 다음과 같은 이유로 필요합니다 info cp.

    심볼릭 링크에서 복사할 때 "cp"는 일반적으로 재귀 없이 복사할 때 링크만 따릅니다.

    -a재귀적 복사( -R)가 활성화되므로 심볼릭 -H링크를 따라야 합니다. -H이는 재귀에도 불구하고 링크가 계속 추적되고 결과적으로 대상 디렉터리에 하드 링크가 설정된다는 의미입니다. 다음은 c/마지막 단계 이후에 나오는 내용입니다(첫 번째 열은 inode 번호입니다).

    $ ls -li c 
    total 0
    17044704 -rw-r--r-- 2 terdon terdon 0 Oct  9 02:50 a
    17044704 -rw-r--r-- 2 terdon terdon 0 Oct  9 02:50 b
    

이제 그것이 정확히 어떻게 작동하는지에 대해, 다음과 같은 경우 심볼릭 링크를 하드 링크로 사용, cp --preserve=links결합 -L또는 변환하여 알아낼 수 있습니다.-H링크와 대상이 모두 복사됩니다.동일한목차.


사실 OP로서발견하다적어도 데비안 시스템에서는 cp --preserve=links대상 디렉터리가 동일하면 심볼릭 링크를 하드 링크로 변환하는 것으로 충분합니다.

답변2

문서에 있을 수 있는 버그에 대한 보고서를 coreutils team@gnu.org로 보냈고 info cp답변을 받았습니다.

여기에 있는 문서는 약간 간결합니다. 주요 문제는 -a가 -d를 의미하고 명령이 예상대로 작동하도록 하는 데 필요한 --no-dereference를 의미한다는 것입니다. cp가 소스의 심볼릭 링크를 따르는 것을 암시적으로 중지하려면 IE --no-dereference가 필요합니다.

여기에 설명된 세부정보를 확인하고 분할하려면 다음을 수행하세요.

$ mkdir links; : > a; ln -s a b;

여기서는 -d가 다음 -H를 재정의한다는 것을 알 수 있습니다. 따라서 우리는 애초에 심볼릭 링크를 역참조하지 않습니다.

$ rm links/*; cp -H -d a b links
$ l links/
lrwxrwxrwx. 1 padraig 1 Oct 10 09:37 b ▪▶ a
-rw-rw-r--. 1 padraig 0 Oct 10 09:37 a

여기서는 -H가 마지막에 오기 때문에 존중되므로 소스에서 심볼릭 링크를 따르고 결과적으로 대상에서 하드 링크가 생성된다는 것을 알 수 있습니다.

$ rm links/*
$ rm links/*; cp -d -H a b links
$ l links
-rw-rw-r--. 2 padraig 0 Oct 10 09:37 b
-rw-rw-r--. 2 padraig 0 Oct 10 09:37 a

다음을 통해 문서를 더욱 명확하게 만들겠습니다.

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index b273627..aeed4ca 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -8257,9 +8257,11 @@ $ mkdir c; : > a; ln -s a b; cp -aH a b c; ls -i1 c
 @noindent

입력:은 @file{b}일반 파일에 대한 심볼릭 링크이지만 @file{a}대상 디렉터리의 파일은 @file{c/}하드 링크입니다.

  • @option{-a}힌트 때문에 @option{--preserve=links}그리고 명령줄 인수를 역참조하라는 @option{-H}지시를 받았기 때문에 동일한 inode 번호를 가진 두 개의 파일을 보고 인식된 하드 링크를 유지합니다.@command{cp}
  • 왜냐하면 심볼릭 링크를 복사한다는 @option{-a}@option{--no-dereference}이지만 후자는 명령줄 인수를 역참조하라는 @option{-H}@command{cp}이므로 동일한 inode 번호를 가진 두 개의 파일이 표시됩니다. 그러면 이 @option{--preserve=links} 옵션은 @option{-a}인지된 하드 링크가 보존된다는 것을 의미합니다.

답변3

하드 링크를 심볼릭 링크로 변환하는 것은 어렵습니다. 하드 링크의 경우 파일 시스템에 두 개 이상의 파일 항목이 이를 가리키는 데이터 블록이 있습니다. "소스"와 "대상"은 없습니다. 실제로는 동일한 이름이 여러 개 있는 하나의 파일입니다. GNU find를 사용하여 다음을 식별할 수 있습니다.

sauer@zipper:~$ find . -type f -links +1 -printf "%i: %p (%n)\n"
609: ./link1 (2)
609: ./link2 (2)

동일한 inode를 가진 모든 파일이 있으면 하나를 "실제" 파일로 선택한 다음 다른 모든 파일을 기본 파일에 대한 심볼릭 링크로 바꿔야 합니다. 가능한 방법은 다음을 사용하는 것입니다.

sauer@zipper:~$ find . -type f -links +1 -printf "%i %p\n" | sort -nk1
609 ./link1
609 ./link2

그런 다음 동일한 숫자를 가진 값 중 하나를 선택하여 다른 모든 값을 연결하는 방법을 스크립트에서 알아내도록 하세요. 아마도 첫 번째 노드가 대상이 되고 동일한 inode를 가진 다른 노드가 해당 노드에 심볼릭 링크될 수도 있습니다. 이것은 매우 간단하고 테스트되지 않은 쉘 스크립트 예입니다.

#!/bin/sh
prev=""
target=""
find /tmp -type f -links +1 -printf "%i %p\n" | sort -nk1 \
| while read inode file
do
  if [[ $inode != $prev ]]
  then
     target="$file"
     prev=$inode
  else
    ln -sf "$target" "$file"
  fi
done

find의 경로(이 경우 /tmp)가 절대 경로가 아닌 경우 잘못된 대상으로 다른 디렉터리의 링크가 생성될 수 있으므로 잠재적인 문제가 있습니다. 그러나 일반적인 아이디어는 괜찮을 것입니다.

관련 정보