본문 바로가기

Linux

여러 파일에 있는 문자열을 치환하는 방법

[출처] : http://www.mahome.net/index.php?mid=normal&page=18&document_srl=2873

아래 블로그의 내용을 토대로 사용하면 된다..
방법 : 하위 전체 폴더에서 해당 파일을 찾아 수정.

이제 하위 폴더에서 java 파일에 기록된 @Override를 공백으로처리하고 싶을때는 이렇게 하면 된다.

find . -name "*.java" -exec perl -pi -e 's/\@Override/ /g' {} \;

특수문자 앞에는 '\'를 입력함에 주의하자.

몇가지 예를 들면 다음과 같은것도 변경 가능하다.

1. printf("not implemented");   => //printf("not implemented");
위에서처럼 printf에 주석 처리를 하고 싶으면 다음과 같이 하면 된다.
find . -name "*.cpp" -exec perl -pi -e 's/printf/\/\/printf/g' {} \;

2. #include "macros.h"  => //#include "macros.h"
인클루드 문을 주석처리하고 하는것도 마찬가지이다.
find . -name "*.cpp" -exec perl -pi -e 's/\#include "macros.h"/\/\/#include "macros.h"/g' {} \;

그럼 수고.. :)

 추가사항!!
이런 내용을 Makefile에 넣어서 수정해보았다.
몇번의 삽질을 하긴 했지만 나름 잘 되는구만
-exec의 argument의 마지막 부분인 \; -> +로 바꿔야 한다.
아래 코드를 참고하자

.PHONY: openssl
openssl: mkdir
@if [ ! -d $(OPENSSL_OUT_PATH) ]; then mkdir -p $(OPENSSL_OUT_PATH); fi
@if [ ! -d $(OPENSSL) ]; then tar xvzf $(OPENSSL).tar.gz; fi
@if [ ! -f $(OPENSSL)/Makefile ]; then \
cd $(OPENSSL); \
if [ $(ARCH) ]; then \
./Configure $(ARCH)-elf --prefix=$(OPENSSL_OUT_PATH) \
--openssldir=$(OPENSSL_OUT_PATH) shared no-threads no-asm no-zib || exit 1 ; \
find . -name "Makefile" -exec perl -pi -e 's/\= ar/\= $(ARCH)-ar/g' {} +; \
find . -name "Makefile" -exec perl -pi -e 's/\/usr\/bin\/ranlib/$(ARCH)-ranlib/g' {} +; \
make; \
make install; \
fi \
fi



한가지 더!!

파일 이름을 일괄 변경하는 방법이 있어요..
DummyAAA.cpp, DummyBBB.cpp 이런식의 파일이 있을때 앞에 Dummy를 erato로 변경하고자 한다면
find . -name "*.cpp" | sed -e 'p' -e 's/Dummy/erato/g' | xargs -n 2 mv
위처럼 하면 eratoAAA.cpp, eratoBBB.cpp라고 바뀐다.
명령어 끝에 mv는 mv의 명령어이고, 만약 복사를 하려면 cp로 바꾸면 된다네.

아 그리고 Dummy만 없애고 싶다면 DummyAAA.cpp -> AAA.cpp로 말이지.
그렇다면 아래처럼 그냥 암것도 안넣어주면 된다는..
find . -name "*.cpp" | sed -e 'p' -e 's/Dummy//g' | xargs -n 2 mv


아 또 한가지 더 
이건 파일의 확장자를 바꾸는 기능!!
find ./ | grep cpp | sed "s/\(.*\)\.cpp$/mv '&' '\1.cxx' /" | sh
*.cpp -> *.cxx로 바꾼다.

조금 더 응용하자면 Dummy*.cpp라는 녀석만 바꾸고 싶다면
find ./ -name "Dummy*.cpp" | grep cpp | sed "s/\(.*\)\.cpp$/mv '&' '\1.cxx' /" | sh
요렇게 해서 Dummy*.cpp를 찾아서 이녀석들만 바꿀수도 있다.


아래는 복사 하는 방법
find . -name "*.h" -exec cp {} ./include/ \;

================================================================

만약 특정 디렉토리 이하에서 network 라는 문자열을 포함한 화일을 찾고싶다면.. 해당 디렉토리에서 모든 화일을 읽어 찾아보아야 하나.. 다음과 같이 find 와 grep 를 파이프로 연결하여 사용하면 쉽게 찾을 수있다. 

find /etc/ -type f -exec grep 'network' {} /dev/null \; 

위와 같이 명령어를 타입하면 /etc/ 디렉토리 이하에서 network 라는 문자열을 포함한 모든 화일명과 위치를 listing 해 준다. 

그리고 단순히 특정 단어를 포함한 화일명을 찾고 싶으면 locste 라는 것을 쓰면 된다.
즉, locate ftp 를 하면 ftp 라는 화일명이 포함된 화일들을 listing 해 준다.

 

 

find ./ -name "*.zone" -exec perl -pi -e 's/\$TTL\t10800/\$\TTL\t12800/g' {} \;

 

 

-> 현재디렉토리 아래에 zone으로 끝나는 파일들 중에서 $TTL 10800 이라는 문자열을 $TTL 12800

 

으로 치환 하겟다! ㅋ

 

특수문자는 앞에 역슬래쉬를 붙여준다.

 

 

정규표현식 졸래복잡해!

 

 

find /home/ -type f -exec grep 'eval(base64_decode' {} /dev/null \;

 

 

-----------------------------------------------------------------------------------

 

vim 이나 emacs사용자 분들의 경우 ctags 와 같은 플러긴을 사용하여 함수의 선언 및 사용처를 일일히 다 파악할 수 있습니다만,

ctags를 사용할 수 없는 타 플랫폼의 경우 쉘에서의 명령으로 특정 문자열이 들어있는 파일을 찾아야 할 것입니다.

 

웹에서의 검색 결과로는 참으로 다양한 결과물들이 쏟아져 나오는데 그나마 그 중에서 제일 간단한 방법으로는 아래와 같습니다.

 

find (find_root) -name "*" | xargs grep ANY_STRING;

 

사용 예시로는 ...

 

find /usr1/firefox/src -name "*.h" |  xargs grep foo

 

/usr1/firefox/src  라는 디렉토리로부터 모든 C언어 헤더파일을 검색하는데 이 파일에는 foo라는 문자열이 있어야 합니다.

이렇게 되면 /usr1/firefox/src 이하 foo가 들어간 모든 C언어 헤더 파일을 검색할 수 있습니다.

 

문제는 여기서 공백이 포함된 파일명은 검색할 수 없습니다.  그래서 공백을 포함하기 위해

 

find (find_root) -type f -print0 | xargs -0 grep ANY_STRING;

 

을  사용하시면 됩니다. 만약 현재 디렉토리를 기준으로 한다면 굳이 pwd 명령을 쳐서 나온 경로를 치지 않고도

"그냥 (find_root)  자리에 점 하나 찍어 주면 된다" 라는 것 쯤은 누구나 다 알고 계시겠지요?



======================================================================

// header
find . -name "*.h" -exec perl -pi -e 's/IDescriptor\.h/Descriptor\.h/g' {} \;

find . -name "*.h" -exec perl -pi -e 's/snowdrop\_mpeg2ts\ \*\//en\_300\_468\ \*\/\n\}\ \/\*\ namespace\ snowdrop\ \*\/\n/g' {} \;

find . -name "*.h" -exec perl -pi -e 's/snowdrop\_mpeg2ts/snowdrop\n\{\nnamespace\ en\_300\_468/g' {} \;

find . -name "*.h" -exec perl -pi -e 's/IDescriptor/snowdrop\:\:mpeg2ts\:\:Descriptor/g' {} \;

find . -name "*.h" -exec perl -pi -e 's/Descriptor\(\)/Descriptor\(int\ tag\,\ u\_char\*\ data\,\ size\_t\ length\)\;\n/g' {} \;

find . -name "*.h" -exec perl -pi -e 's/\{\}//g' {} \;

find . -name "*.h" -exec perl -pi -e 's/I//g' {} \;

find . -name "*.h" -exec perl -pi -e 's/u\_long/u\_int/g' {} \;

find . -name "*.h" | sed -e 'p' -e 's/I//g' | xargs -n 2 mv

// source
find . -name "*.cpp" -exec perl -pi -e 's/snowdrop\_mpeg2ts\ \*\//en\_300\_468\ \*\/\n\}\ \/\*\ namespace\ snowdrop\ \*\/\n/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/snowdrop\_mpeg2ts/snowdrop\n\{\nnamespace\ en\_300\_468/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/\<\ length\)/\<\ length\(\)/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/\&\(\(u\_char\*\)\ data\)\[0\]\,\ length/data\(\)\,\ length\(\)/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/int\ tag\,\ int\ length/int\ tag\,\ u\_char\*\ data\,\ size\_t\ length/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/a\(/ar\(/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/a\./ar\./g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/datar/data/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/void\*\ data\,\ size\_t\ length//g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/data\ \&\&\ \(//g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/\:\ mDescriptor\(tag\,\ length\)/\:\ Descriptor\(tag\,\ \"\"\,\ data\,\ length\)/g' {} \;

find . -name "*.cpp" -exec perl -pi -e 's/\"Log\.h\"/\<stdio\.h\>/g' {} \;