perl -i가 심볼릭 링크를 깨지 않게 만드는 방법이 있나요?

perl -i가 심볼릭 링크를 깨지 않게 만드는 방법이 있나요?

내 친구는 이렇게 하면 다음과 같이 지적했습니다.

perl -pi.bak -e 's/foo/bar/' somefile

"somefile"이 실제로 심볼릭 링크인 경우 Perl은 문서에 명시된 대로 정확하게 수행합니다.

입력 파일의 이름을 바꾸고, 원래 이름으로 출력 파일을 열고, 해당 출력 파일을 print() 문의 기본 파일로 선택하여 이를 수행합니다. 확장자(제공된 경우)는 백업 복사본을 만들기 위해 이전 파일의 이름을 수정하는 데 사용됩니다. [...]

이로 인해 변경되지 않은 실제 파일을 가리키는 새로운 심볼릭 링크 "somefile.bak"와 변경 사항이 포함된 새로 변경된 일반 파일 "somefile"이 생성됩니다.

대부분의 경우 기호 링크를 따르는 것이 원하는 동작입니다(.bak 파일의 올바른 위치가 불분명해지더라도). 래퍼에서 심볼릭 링크를 테스트하고 상황을 적절하게 처리하는 것 외에 이를 수행할 수 있는 쉬운 방법이 있습니까?

( sed가치가 있는 만큼 동일한 작업을 수행합니다.)

답변1

작은지 알고 싶어요sponge일반 유틸리티("표준 입력을 받아 파일에 쓰기")더 많은 유틸리티이 경우 심볼릭 링크를 따르는지 여부가 도움이 될 것입니다.

작가설명하다 sponge이와 같이:

Unix 도구를 사용하여 파일을 내부 편집할 때 발생하는 문제를 해결합니다. 즉, 편집하려는 파일로 출력을 리디렉션하면 파이프라인의 첫 번째 명령이 수행되기 전에 리디렉션이 적용됩니다(파일 내용 손상). 이제 파일을 읽을 시간입니다. 및 같은 sed -i스위치를 사용 perl -i하면 이 문제를 해결할 수 있지만 파이프라인에서 사용하려는 모든 명령에 이러한 옵션이 있는 것은 아니며 어쨌든 다중 명령 파이프라인에서는 해당 방법을 사용할 수 없습니다.

나는 보통 다음과 같은 스펀지를 사용합니다.

sed '...' file | grep '...' | sponge file

답변2

심볼릭 링크가 존재한다는 사실을 알고 있는 경우 다음을 somefile사용하여 파일의 전체 경로를 명시적으로 제공할 수 있습니다.

perl -pi.bak -e 's/foo/bar/' $(readlink somefile)

이렇게 하면 원본 파일을 사용하여 교체가 직접 수행되므로 원본 심볼릭 링크는 변경되지 않은 상태로 유지됩니다.

답변3

단일 파일을 처리하는 경우 명령은 다음과 같습니다.

perl -i -pe'...' -- "$qfn"

그러면 해결책은 다음과 같습니다.

perl -i -pe'...' -- "$( readlink -e -- "$qfn" )"

이는 기호 링크와 비기호 링크를 모두 처리합니다.


임의로 많은 수의 파일을 처리하는 경우 명령은 다음과 같습니다.

... | xargs -r perl -i -pe'...' --

그러면 해결책은 다음과 같습니다.

... | xargs -r readlink -ze -- | xargs -r0 perl -i -pe'...' --

이는 기호 링크와 비기호 링크를 모두 처리합니다.


경고하다 readlink표준 명령이 아니므로 해당 명령의 존재, 매개변수 및 기능이 시스템마다 다르므로 설명서를 확인하십시오. 예를 들어, 일부 구현에는 -f(여기에서도 사용할 수 있음)이 있지만 그렇지 않은 경우도 있고 -e, 둘 다 없는 경우도 있습니다. busybox동작 은 readlink -fGNU 와 유사합니다 readlink -e. 일부 시스템에는 일반적 realpath으로 readlinkGNU처럼 동작하는 명령이 있습니다 readlink -f.

GNU를 사용할 때 readlink -e기존 파일로 해석될 수 없는 심볼릭 링크는 자동으로 삭제됩니다.

관련 정보