심볼릭 링크를 파일로 바꾸기


31

모든 심볼릭 링크를 링크 된 파일로 바꾸는 쉬운 방법이 있습니까?


3
어떤 문제를 해결하려고합니까?
Daniel Beck

3
다른 드라이브에 대한 많은 상징적 링크가 있습니다. 다른 곳에서 참조되는 드라이브에서 모든 파일을 제거해야 제거 할 수 있습니다.
Marty Trenouth 2016 년

답변:


14

"easy"의 일부 정의의 경우 :

#!/bin/sh
set -e
for link; do
    test -h "$link" || continue

    dir=$(dirname "$link")
    reltarget=$(readlink "$link")
    case $reltarget in
        /*) abstarget=$reltarget;;
        *)  abstarget=$dir/$reltarget;;
    esac

    rm -fv "$link"
    cp -afv "$abstarget" "$link" || {
        # on failure, restore the symlink
        rm -rfv "$link"
        ln -sfv "$reltarget" "$link"
    }
done

링크 이름을 인수로하여이 스크립트를 실행하십시오. 예 : find . -type l -exec /path/tos/script {} +


2
편집에 감사드립니다. 그러나 스크립트 필요한 모든 위치에 변수를 인용하여 공백이있는 파일 이름을 처리합니다. 변경 "$var"하려면 "${var}"쉬 / bash는 아무것도 실행이다. 나는 하나의 bashism ( [[)을 제거했으며 나머지는 POSIX sh와 호환됩니다.
grawity

symlink 실패를 처리하기위한보다 강력한 방법 cp은 동일한 디렉토리에있는 임시 파일과 mv -f해당 임시 파일을 원본 파일로 만드는 것입니다. 이렇게하면 사람들 Ctrl-C이 파일 시스템을 잡고 있거나 파일 시스템이 rmcp명령 사이에 채워지 는 등의 문제 를 방지 할 수 있습니다 (따라서 새로운 기능도 ln작동 하지 못하게 함 ). ls -a필요한 경우 나중에 정리할 수 있도록 임시 파일 이름을 쉽게 찾을 수 있습니다.
Mr Fooz

부수적으로, 나는 왜 사건 블록 abstarget=$(readlink -f "$link")대신에 왜 사용하지 않았는지를 진지하게 기억하지 못하지만 이식성 이유 일 수 있습니다.
grawity

17

tar를 사용하여 데이터를 새 디렉토리에 복사하는 것이 더 쉬울 수 있습니다.

-H      (c and r mode only) Symbolic links named on the command line will
        be followed; the target of the link will be archived, not the
        link itself.

이런 식으로 사용할 수 있습니다

tar -hcf - sourcedir | tar -xf - -C newdir

tar --help:
-H, --format=FORMAT        create archive of the given format
-h, --dereference          follow symlinks; archive and dump the files they point to

1
귀하의 솔루션을 사랑하지만 메시지의 마지막 부분을 이해하지 못합니다. 나를 위해 당신이해야 :tar -hcf - sourcedir | tar -xf - -C newdir
Seb DA ROCHA

1
이 답변은 의견에 따라 업데이트해야합니다.
astabada

1
cp -L더 간단한 해결책입니다
plesiv

@plesiv true 및 posix 호환이지만 모든 cp구현이 디렉토리를 복사 하지는 않습니다 .
Wyatt8740

16

내가 당신을 올바르게 이해했다면 명령 의 -L플래그 cp가 정확히 원하는 것을해야합니다.

모든 심볼릭 링크를 복사하기 만하면 심볼릭 링크가 가리키는 파일로 대체됩니다.


4
고마워-내가 필요한 거의 : 나는 뭔가를해야했다 : cp -L files tmp/ && rm files && cp tmp/files . 당신이 명확히하면, 당신은 아마 더 많은 사람들을 도울 것입니다 ...
sage

5

"쉬운"은 아마도 당신의 기능 일 것입니다.

"find"명령 행 유틸리티를 사용하여 심볼릭 링크 된 파일을 찾은 다음 rm 및 cp를 호출하여 파일을 제거하고 교체하는 스크립트를 작성했을 것입니다. sym 링크를 이동하기 전에 충분한 여유 공간이 남아 있는지 찾기 확인으로 호출되는 작업을 수행하는 것이 좋습니다.

또 다른 해결책은 문제 링크를 숨기고있는 삼바와 같은 것을 통해 문제의 파일 시스템을 마운트 한 다음 모든 것을 복사하는 것입니다. 그러나 많은 경우에 이와 같은 것이 다른 문제를 야기 할 수 있습니다.

귀하의 질문에 대한보다 직접적인 답변은 "예"일 것입니다.

편집 : 더 구체적인 정보 요청에 따라. findman 페이지에 따르면 이 명령은 모든 sym 링크 파일을 /에서 2 개 디렉토리 깊이까지 나열합니다.

find / -maxdepth 2 -type l -print

( 여기에서 발견되었습니다 )

찾을 때 무언가를 실행하려면 :

find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;

방금 작성한 스크립트를 호출하고 방금 찾은 파일 이름을 전달합니다. 또는 찾기 출력을 파일로 캡처 한 후 ( "find [blah]> symlinks.data"등 사용) 원본을 정상적으로 복사하기 위해 작성한 스크립트로 해당 파일을 전달할 수 있습니다.


? 약간 일반적인 것-정교하게 할 수 있습니까?
Linker3000

2
구문은-exec ./ReplaceSymLink.sh {} \;
grawity

항목을 찾게되며 답변으로 표시된 항목이 링크를 대체하는 데 사용됩니다!
Marty Trenouth

3

이것은 내가 사용한 oneliner입니다. 모든 로컬 파일이 "source"의 다른 파일에 대한 링크라고 가정하십시오. 패턴 또는 "찾기"로 파일 선택을 세분화 할 수 있습니다. 사용하기 전에 이해하십시오.

f in *; cp --remove-destination source / $ f $ f; 끝난

이것이 도움이되기를 바랍니다.


readlink를 사용하는 방법 : f in *; cp ---- remove-destination "$ (readlink $ f)" "$ f"; 완료
Diego

예, 좋은 생각이지만 작업에 대한 통제력을 잃습니다. 내 솔루션의 한 가지 한계는 중간에 공백이 있거나 매우 긴 목록에 대해서는 파일이 작동하지 않는다는 것입니다. 아마도 마지막 해결책은 위의 'find --exec'를 'remove destination'과 결합하는 것입니다. 아무도 시도하고 싶어?
MastroGeppetto

중간에있는 공백은 큰 따옴표로 "$ f"를 넣어서 완화해야합니다. 다음은 "for loop"대신 "find & xargs"와 함께 사용하는 방법입니다. find ./ -type l -print0 | xargs -0 -n1 -i sh -c 'cp --remove-destination $ (readlink "{ } ")"{} " '가시성에 대한 별도의 답변으로 게시했습니다. superuser.com/a/1329543/499386
Diego

2
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;

에서 각 심볼릭 링크 된 파일 / 폴더의 사본을 만듭니다. 파일을 <filename>.dereferenced직접 바꾸는 것보다 안전합니다 (더 편리하지 않은 경우). 복사 된 데이터를 심볼릭 링크의 파일 이름으로 이동하는 것은 독자의 연습으로 남아 있습니다.


2

이전 아이디어 중 일부를 사용하여 다음 명령은 모든 symlink를 원본의 사본으로 재귀 적으로 바꿉니다.

find . -type l -exec bash -c "echo 'Replacing {} ...';  cp -LR '{}' '{}'.dereferenced;  rm '{}';  mv '{}'.dereferenced '{}'" \;


1

거기에 좋은 답변이 많이 있지만 당신이 쉬운 것을 찾고 있었던 이래로

for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done

약간의 향상은 심볼릭 링크를 찾는 데 도움이 될 것입니다 : lfin for`find. -타입 l`; src = $ (readlink $ lnk) && rm $ lnk && mv $ src $ lnk; 완료 (계층 구조로 테스트되지 않았지만 백틱에주의하십시오)
Roman Susi 2013

1

링크를 따라 파일을 복사 할 것으로 예상 할 때 gwenview 복사 링크와 동일한 문제가 발생했습니다.

모든 링크를 따르고 모든 지정된 파일을 디렉토리에 복사하여 디렉토리를 '정리'한 것은 스크래치 디렉토리를 작성하는 것입니다.

"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./" 

점검이 없기 때문에 스크립트에 넣기가 너무 위험하지만 내 문제가 해결되었습니다.



0

내 웹 호텔이 bash 스크립트를 허용하지 않았기 때문에 한 줄 버전을 사용했는데 나에게 잘 작동했습니다.

before:
> find . -type l | wc -l
358

> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...

after:
> find . -type l | wc -l
0
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.