Mac 및 Linux의 텍스트 파일에서 재귀 검색 및 바꾸기


127

리눅스 쉘에서 다음 명령은 재귀 적으로 'this'의 모든 인스턴스를 'that'으로 검색하고 바꿉니다 (내 앞에 Linux 쉘이 없지만 그렇게해야합니다).

find . -name "*.txt" -print | xargs sed -i 's/this/that/g'

OSX에서 비슷한 명령은 어떻게 생깁니 까?


아마도 apple.stackexchange.com리눅스 나 모든 개발자들에게는 일반적인 것이 아니기 때문에 아마 옮겨야 할 것입니다 .
AlikElzin-kilaka

답변:


246

OS X은 BSD와 GNU 도구를 혼합하여 사용하므로 항상 문서를 확인하는 것이 가장 좋습니다 ( lessOS X 맨 페이지를 준수하지 않은 문서도 있음).

https://web.archive.org/web/20170808213955/https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html

sed는 -i백업의 확장명으로 after 인수를 사용합니다. -i ''백업하지 않으 려면 빈 문자열 ( )을 제공하십시오 .

다음을 수행해야합니다.

LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +

-type f단지 좋습니다; sed는 디렉토리를 주면 불평합니다. -exec보다 바람직하다 xargs; 귀찮게 할 필요가 없습니다 -print0. {} +마지막 수단에서 find대신, 호출 명령의 한 인스턴스에 인수로 모든 결과를 추가합니다 각각의 결과를 도출하기 위하여 해당 정보를 재 실행. (OS에서 허용하는 최대 수의 명령 줄 인수가 위반되는 경우 find는 예외입니다.이 경우 둘 이상의 인스턴스가 실행됩니다.)


2
이 대체의 "this"에는 슬래시 (localhost / site)가 포함되어 있습니다. URL의 일부를 .html 파일로 대체하고 있습니다. 어떻게 이러한 대체를 수행합니까? 큰 따옴표를 넣으려고했지만 실패합니다.
Timothy T.

6
Sed 구문은 슬래시 대신 거의 모든 문자를 사용할 수 있습니다. 예를 들어 다음 %문자를 사용할 수 있습니다 sed "s%localhost/site%blah/blah%". 또 다른 대안은 구분 기호를 백 슬래시 이스케이프 처리하는 것 sed "s/localhost\/site/blah\/blah/"입니다.
TaylanUB

당신이 그것을 시도하게 해 주셔서 감사합니다. 그러나 슬래시를 분리하기 위해 {}를 사용하려고 시도했지만 여전히 오류가 발생합니다 ...
Timothy T.

16
다른 사람이 illegal byte sequence오류가 있습니까? 그렇다면 시도하십시오 : LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +, 그것은 나를 위해 일했습니다.
ColdTuna

10
이것은 단지 하나의 파일 당 ocurreny 사용을 대체 할 것 /g같은 여러 ocurrencies 위해LC_ALL=C find . -type f -exec sed -i '' s/search/replace/g {} +
jamesjara

152

맥의 경우 더 비슷한 접근 방식은 다음과 같습니다.

find . -name '*.txt' -print0 | xargs -0 sed -i "" "s/form/forms/g"

10
다시 돌아와서 사용할 때마다이를 공표 할 수 있기를 바랍니다. 지금은 +15에있었습니다.
드루 건

어떤 이유로 든, 그것은 나를 위해 작동하지 않습니다. 아무것도하지 않습니다. form360 폴더 안에 있고 easyform이라는 이름으로 모든 문자열 인스턴스를 form360으로 변경하려고합니다. 다음 명령을 실행하고 있습니다.find . -name '*.php' -print0 | xargs -0 sed -i "" "s/easyform/form360/g"
Andres Ramos

2
나를 위해, 이것은 정답이어야합니다. 나를 위해 일한 유일한 사람입니다.
코켈 디비

1
-print0 | 파일 이름에 공백이 있으면 xargs -0이 Mac에서 작동하지 않습니다.
2807219

1
. 나오지 : 내부 편집 정규 파일에 사용
codeslapper

14

대안 솔루션으로 Mac OSX 10.7.5에서이 솔루션을 사용하고 있습니다.

grep -ilr 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

크레딧 : Todd Cesere의 답변


이것은 잘 작동합니다! 다른 스크립트는 OSX에서 경우에 따라 줄을 추가합니다! 고마워요!
Sebastien Filion

14

Mac OSX 10.11.5에서는 다음과 같이 작동합니다.

grep -rli 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

xargs -I @ sed -i '' 's / old-word / new-word / g'@는 다른 많은 작동하지 않는 제안을 시도한 후에 저를 위해 일했습니다. 감사합니다!
DrB

13

위의 어느 것도 OSX에서 작동하지 않습니다.

다음을 수행하십시오.

perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt

1
SEARCH_FOR 및 REPLACE_WITH가 경로 인 경우 '/'를 피하는 방법은 무엇입니까?
rraallvv

다른 구분자를 사용하십시오. 경로를 사용하는 경우 콜론이나 파이프가 작동합니다. 예를 들어, 's | SEARCH | REPLACE | g'. 's {SEARCH} {REPLACE}'에서와 같이 중괄호를 사용합니다.
dannysauer

1
dito 질문, Mac에서는 시도하지 않지만 오류가 발생하는 것 같습니다. 예를 들어 내 경로가 파일로 해석됩니까? -bash : localhost / nohost : 해당 파일이나 디렉토리가 없음
Timothy T.

폴더 깊이까지는 되풀이되지 않습니다. 단 하나의 레벨.
Sergey Romanov

이 명령에 대한 자세한 내용은 lifehacker.com/5810026/…를 참조하십시오.
kuzdu

7

Linux 및 Mac OS X 모두에서 작동하는 버전 ( -e스위치를 에 추가하여 sed) :

export LC_CTYPE=C LANG=C
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/this/that/g'

이 답변에서 내보내기 + 허용 된 답변의 라인을 수행해야했습니다 (백업 파일 생성을 원하지 않음)
Lance

2
'잘못된 바이트 시퀀스'오류를 해결하려면 명령을 실행하기 전에 LOCALE을 설정하십시오. export LC_CTYPE=C && export LANG=C
cjoy

Git을 사용하는 경우처럼 '* .filetype'대신 '*'로 이것을 실행하지 마십시오. 또는 게시되지 않은 모든 작업에 작별 인사를 할 수 있습니다.
Sergey

1
sed 명령의 mac 버전에는 -i 뒤에 ''가 필요
G Huxley

2

이 명령을 입력 할 때마다 항상 명령을 내리거나 깃발을 잊어 버리는 것 같습니다. TaylanUB의 답변을 기반으로 현재 디렉토리에서 전역 찾기를 수행하는 github에서 Gist를 만들었습니다. 이것은 Mac OSX 전용입니다.

https://gist.github.com/nateflink/9056302

이제 터미널을 열어서 복사하기 때문에 좋습니다.

컬 -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

이상한 바이트 시퀀스 오류가 발생할 수 있으므로 전체 코드는 다음과 같습니다.

#!/bin/bash
#By Nate Flink

#Invoke on the terminal like this
#curl -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: ./$0 [find string] [replace string]"
  exit 1
fi

FIND=$1
REPLACE=$2

#needed for byte sequence error in ascii to utf conversion on OSX
export LC_CTYPE=C;
export LANG=C;

#sed -i "" is needed by the osx version of sed (instead of sed -i)
find . -type f -exec sed -i "" "s|${FIND}|${REPLACE}|g" {} +
exit 0

2

이것은 나의 실행 가능한 것입니다. Mac OS X 10.10.4에서

grep -e 'this' -rl . | xargs sed -i '' 's/this/that/g'

위의 것들은 find 를 사용 하여 검색 텍스트를 포함하지 않는 파일을 변경합니다 (파일 끝에 새 줄을 추가하십시오).


2

zsh 터미널을 사용하는 경우 와일드 카드 매직을 사용할 수 있습니다.

sed -i "" "s/search/high-replace/g" *.txt


1

나는이 형식을 사용했지만 ... 매우 이상하게 발견 된 모든 인스턴스를 실제로 변경하려면 3 번 이상 실행해야한다는 것을 알았습니다. 한 번 실행하면 각 파일의 일부가 변경되지만 전부는 아닙니다. 정확히 같은 문자열을 2-4 번 실행하면 모든 인스턴스를 잡을 수 있습니다.

find . -type f -name '*.txt' -exec sed -i '' s/thistext/newtext/ {} +

g마지막에 sed 정규 표현식이 a / b를 필요로하기 때문에이 명령을 여러 번 b / c로 실행해야했습니다 . 그렇지 않으면 thistext행 의 첫 번째 항목 만 바꿉니다 . 따라서 정규 표현식은s/thistext/newtext/g
Les Nightingill

0

https://bitbucket.org/masonicboom/serp 는 OSX에서 테스트 된 go 유틸리티 (예 : 크로스 플랫폼)로, 주어진 디렉토리 내의 파일에서 텍스트를 재귀 적으로 검색 및 교체하고 각 교체를 확인합니다. 새로운 기능이므로 버그가있을 수 있습니다.

사용법은 다음과 같습니다.

$ ls test
a  d  d2 z
$ cat test/z
hi
$ ./serp --root test --search hi --replace bye --pattern "*"                         
test/z: replace hi with bye? (y/[n]) y
$ cat test/z
bye


-3

OSX의 명령은 예쁜 UI에서 Unix와 정확히 동일해야합니다.


많이 생각했지만 아니 sed로 공급할 때 파일 앞에 ./를 넣으므로 sed는 '잘못된 명령 코드'를 불평합니다. 어쩌면 난 그냥 피곤해 ;-)
Jack

@JacobusR, OSX 터미널에서 잘라내어 붙여 넣으십시오. 약간 다른 것을 입력해야합니다.
glenn jackman 15.02에

3
당신은 할 수 있습니다 -print0받는 추가 find플래그와 -0받는 xargs플래그.
jmtd

또한 -exec sed -i s/this/that/g {} \+대신 -printxargs를 사용할 수 있습니다
Marian

@JacobusR-선행 './'경로 이름이 있어도 작동합니다. 그러나 파일 이름에 공백이 있으면 "./jacobus \ R.txt"라고 말하면 xargs공백으로 구분 된 "./jacobus"를 파일로 전달한 sed다음 "R.txt"와 함께 사용할 수 있습니다. 둘 다 존재하지 않습니다.
Brett Hale

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