펄 -i를 클로버 심볼릭 링크로 만들지 않는 방법이 있습니까?


12

내 친구는 당신이 그렇게하면 :

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

"somefile"이 실제로 심볼릭 링크 인 경우, perl은 문서에서 수행 할 작업을 수행합니다.

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

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

대부분의 경우 심볼릭 링크를 따르는 것이 바람직한 동작입니다 (.bak 파일의 올바른 위치를 모호하게 남겨도). 랩퍼에서 심볼릭 링크를 테스트하고 케이스를 적절하게 처리하는 것 이외의 다른 방법이 있습니까?

( sed가치가있는 것과 같은 일을합니다.)


1
vim 또는 emacs에 전화하십시오 (두 가지 모두 심볼릭 링크를 따르는 것 같습니다)? 진심으로, 나는 대답이 -p -i당신의 대본에서 다시 구현 하는 것 같습니다.
Gilles 'SO- 악마 그만해'

Sed는 실제로 2009 년 6 월에 릴리스 된 버전 4.2.1 이후로는 똑같은 작업을 수행하지 않습니다. symlink를 방해하지 않고 링크 된 파일을 편집하려면 편집에 --follow-symlinks 옵션을 포함시켜야합니다. ; 나는 이것이 이전 행동에 의존 할 수있는 기존 스크립트의 손상을 피하기 위해 수행되었다고 가정합니다.
개렛

답변:


6

moreutils 의 작은 sponge범용 유틸리티 ( "표준 입력을 가져 와서 파일에 쓰기") 가이 경우에 도움이되는지, 그것이 심볼릭 링크를 따를 것인지 궁금 합니다.

저자 는 다음 sponge 과 같이 설명 합니다.

Unix 도구를 사용하여 파일을 편집하는 문제를 해결합니다. 즉, 출력을 편집하려는 파일로 출력을 리디렉션하면 파이프 라인의 첫 번째 명령 전에 리디렉션이 적용됩니다 (파일의 내용을 복제). 파일에서 읽습니다. 같은 스위치 sed -iperl -i이 문제를 해결하지만, 당신이 파이프 라인에 사용할 수없는 모든 명령은 옵션이 있습니다, 당신은 어쨌든 여러 명령 파이프 라인과 그 방법을 사용할 수 없습니다.

나는 보통 다음과 같이 스폰지를 조금 사용합니다.

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

이봐, 멋지다. 위의 Gilles의 의견은 "진정한"답변이라고 생각하지만, 답변으로하지 않았기 때문에 새로운 유틸리티를 배운 이후에 이것을 사용할 것입니다. :)
mattdm

그러나 sponge실제로 그러한 사용법 을 테스트 했습니까? 나에 관해서는 : 아직. 테스트에서 원하는 방식으로 동작했는지 여부를 알려주는 의견을 남겨 주시겠습니까? 아, 댓글이 보여요. 확인 감사합니다!
imz-Ivan Zakharyaschev

— 네, 답장을하기 전에 시도했습니다. 때 file당신의 예에서 위의 심볼릭 링크, 링크가 방치하고 실제 파일이 변경되었습니다.
mattdm

@ mattdm : 예, 확인 감사합니다! (내 의견을 쓴 것보다 조금 늦게 당신의 말이 작동하는 것을
보았습니다

3

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

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

이렇게하면 원본 파일로 직접 교체되므로 원본 심볼릭 링크는 그대로 유지됩니다.


그러나 출력 readlink은 여전히 ​​다른 심볼릭 링크 일 수 있습니다. 베스트 사용하는 것 -f또는 -e가능한 경우 또는 zsh$file:P또는 (:P)규정 glob에 @ikegami 같이 심볼릭 링크가없는 경로를 얻을 수 있습니다.
Stéphane Chazelas

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일부는 없습니다. busyboxreadlink -fGNU와 같은 동작합니다을 readlink -e. 그리고 일부 시스템에는 일반적으로 GNU처럼 동작 하는 realpath명령 이 있습니다 .readlinkreadlink -f

GNU readlink -e에서는 기존 파일로 확인할 수없는 심볼릭 링크가 자동으로 제거됩니다.


@ Stephane Chazelas $var:P는 나를 위해 작동하지 않습니다. ( X='tmp' zsh -c 'perl -E"say for @ARGV" $X:P'출력 tmp:P)
ikegami

에 대해 zsh 5.3 (2016) 이상이 필요 $var:P합니다. 이전 버전에서는 항상 $var:A대신 사용할 수 있습니다 . 차이점에 대한 매뉴얼zsh.org/mla/users/2016/msg00593.html:P (실제 realpath()인터페이스) 소개에 대한 이론적 근거를 참조하십시오 .
Stéphane Chazelas

( 2012 년 :AGNU 4.3.10 (2009)에 추가되었으며 readlink -z, readlink을 지원 하는 다른 구현에 대해서는 알지 못합니다 -z). GNU xargs에서는 -r입력이 비어 있지 않다고 보장 할 수 없다면 일반적으로 옵션을 원합니다 . 여기에는 perl코드가 BEGIN/ END문을 포함 하지 않는 한 큰 문제가되지 않습니다 -i used with no filenames on the command line, reading from STDIN.. 그렇다면 경고 가 표시됩니다.
Stéphane Chazelas

죄송합니다 -r. 설명서를 잘못 읽었습니다 . 나는 그것이하는 것과 반대되는 것을 생각했습니다. 읽었습니다.
ikegami
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.