변경된 파일의 백업 만 생성하는 sed 전체 대체 방법을 수행하는 방법은 무엇입니까?


13

현재 작업 디렉토리의 모든 파일에 사용 된 용어를 대체하기 위해 다음을 실행했습니다.

$ find . -type f -print0 | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

이 단어 대체를 수행했지만 문자열 .bup이없는 파일 파일 도 만들었습니다 Ms. Johnson.

불필요한 백업을 모두 만들지 않고 대체를 수행하려면 어떻게합니까?


SED의 버그로 날 것으로 보인다 참조
Hotschke

저장하고 종료하기 전에을 사용 ex하고 조건부로 (파일이 변경된 경우에만) 실행 하는 것이 더 나은 방법 일 것입니다 :!cp '%' '%.bup'. 살펴볼 가치가 있습니다.
와일드 카드

스택 교환 에서 위의 아이디어에 대한 질문을 작성했습니다 vi.
와일드 카드

답변:


6

파일 내용을 확인하여 파일을 sed조작 할 때 대체가 발생하는지 확인할 수 있습니다.

find . \
    -type f \
    -exec grep -q 'Ms. Johnson' {} \; \
    -print0 |
xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

당신이 그것에 대해 정말로 영리하고 싶다면, 당신은 find전혀 사용하지 않을 수 있습니다 :

grep -Z -l -r 'Ms. Johnson' |
    xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

1
난 당신이 필요하다고 생각 '{}'당신의 이전 \;에 그 -exec.
Jander

8

Find에는 -exec임의의 명령을 실행 하는 연산자가 있습니다. 더 좋은 -exec것은 테스트 이므로 여러 개의 체인을 -exec함께 연결할 수 있으며 이전 명령이 실패하면 나중에 명령이 실행되지 않습니다. 문자열 {}은 현재 파일 이름으로 바뀌고 ;명령의 끝을 표시합니다. 쉘 간섭을 피하기 위해 둘 다 인용해야합니다.

그래서:

find . -type f \
    -exec grep -q 'Ms. Johnson' '{}' \; \
    -exec sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g' '{}' \;

베어 {}를 사용하는 데 문제가 없었습니다.
amphetamachine

1
@ amphetamachine : 나도 없지만 매뉴얼 페이지에서 제안합니다. csh 일 수도 있고 {}중괄호 확장을 수행 할 때 null 문자열 로 확장 하는 쉘 (Bash가 아닌 POSIX가 아닌)이있을 수 있습니다 .
Jander

4

나는 sed당신이 묻기 전에 당신이 한 것처럼 매뉴얼 페이지를 보았고 그것을 통해 직접 할 수있는 방법을 보지 못했습니다. grep을 사용 하여이 문제를 해결하는 몇 가지 방법이 있지만 가장 쉬운 방법은 다음과 같습니다.

grep -rlZ "Ms. Johnson" . | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

-r재귀
-l인쇄 파일 이름 만
-Znull로 끝나는 이름


-1

검색어와 일치하는 파일 목록을 먼저 작성해야합니다.

search="test"
for match in $(find -type f -exec grep -l $search "{}" \;)
do sed -i'.bup' -e "/$search/ s/$search/Mrs. Melbin/g" "$match"
done

.대한 첫 번째 인수로를 잊었습니다 find. 또한, 얼마 전에 나 자신에 대해 알게되었으므로 실제로 인용하거나 탈출 할 필요가 없습니다.{}
Kevin

파일 목록을 생성하지 말고 명령 대체를 수행하십시오. 먼저 find줄 바꿈으로 구분 된 파일 목록을 생성 한 다음 쉘은이 목록을 줄 바꿈이 아닌 여백에서 분리 한 다음 각 단어를 glob 패턴으로 취급합니다. 파일 이름에 공백이나가 포함되지 않은 경우에만 작동합니다 \[?*. 이 페이지의 다른 답변은 올바르게 수행하는 방법을 보여줍니다.
Gilles 'SO- 악마 그만해

@Kevin .경로가 인자로 전달되지 않을 때 가정되기 때문에 find (적어도 리눅스에서는 find)에는 불필요하다.
laebshade
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.