먼저 이건 철저하게 배포용을 위해서 만든 기술이 아니라 개인 소장용이라는 점을 명백하게 말하겠다.

어떤 사이트를 가 봤는데 맘에 드는 사진이나 그림들이 연달아 나열된 경우가 많다. 로딩도 해야하고 일일이 클릭도 하는게 귀찮아서 그 사진들을 다 다운받아서 만화책 보는 프로그램으로 쭉 보고 싶을때가 있다.

그렇다! 귀찮은 것이다. 귀찮으면 DRY (Don't Repeat Yourself:같은 일을 반복하지 말고 반복하는 일은 전부 컴퓨터에게 맡겨라) 원칙에 따라서 개발자 본능이 꿈틀거린다.

개발자의 종특중 하나는 일일이 눌러서 다운받는게 3시간 걸리는 작업이라도, 개발로 편하게 스크립트 짜는게 6시간이 걸려도 후자를 택하는 종족이기 때문이다. (다만 한번 한 작업은 다음에 할 때 무지하게 빨라진다는 장점이 있다)

이제 부터는 철저하게 시나리오다. 내가 이런다는 것이 절대 아니다.

어느 사이트에 갔더니 만화가 올려져 있다. '엇! 이런 횡재를!!' 게다가 사이트를 보니 소스를 볼 수가 있는 것이다. 1화를 누르고 소스보기를 통해서 그 소스를 happy01.html 로 저장했다. 이제 이걸

$ get-picture.sh happy01.html 1

하면 내가 원하는 그림 파일들이 01-01.png 나 01-01.jpg 이런 형식으로 쭈욱 저장된다. 앞에 01, 02 이런식으로 저장하는건 나중에 만화책 뷰어가 파일 순서를 헷갈리기 때문에 저런 형식으로 저장해줘야 한다.

개별 설명을 하자면 먼저 스크립트다.

#!/bin/bash argc=$# HTML=$1 PART=$2 NUM="1" FILENAME="" if [ $argc -eq 2 ] then cat "${HTML}" | sed -E -f newline.sed | grep -E 'https://www.avsnoop' | \ awk '{print $1}' |while read url ; \ do FILENAME=$(printf "%02d-%02d.%s" "$PART" "$NUM" "`echo "${url}" | sed -E 's/^.*(png|jpg)/\1/'`");\ echo "downloading.. ${url}" ; curl -o "${FILENAME}" "${url}" ;NUM=$[$NUM +1] ;done else echo "Usage: get-picture.sh [HTML name] [Part Number]" fi

위 내용을 긁어서 쓸때는 \개행문자 콤보를 지우고 한줄로 만들어서 쓰는게 좋다. (보기 안좋아서 이리 처리함)

매개변수가 2개가 안되면 사용법을 출력하고 종료하고 매개 변수가 첫번째 html 파일 이름 과 몇 화로 저장할것인지를 지정해주면 동작한다.

cat "${HTML}" 을 통해서 HTML 의 내용을 가지고 오고 그 내용을 sed 에게 넘겨줍니다.

sed 는 스트림 에디터 라고 하는데 보통 넘겨 받은 데이타에서 특정 패턴을 찾아서 지운다던가 패턴을 치환하는 용도로 많이 쓰인다. -E 옵션은 정규표현식을 처리한다는 것이고 -f 는 파일을 읽어서 처리한다는 뜻이다. 보통은 파일 처리를 안하지만 's/A/B/g' 와 같이 치환한다는 가정을 할 때 B 에 개행문자를 포함시켜서 치환이 command line 에서는 적용이 안된다.

newline.sed 를 보면

s/(https:\/\/www\.avsnoop\.com\/files\/2015\/09\/04\/[^/]*\.)(png|jpg)/\
\1\2\
/g

와 같은 식으로 특정 패턴을 찾으면 그 패턴 앞뒤로 \n 개행문자를 넣어주는 치환을 가한다. 이렇게 하는 이유는 sed 명령어 다음에 이어지는 grep 명령이 라인단위로 동작하기 때문에 정해진 패턴을 줄단위로 출력하게 만들기 위해서다.

다만 위의 내용대로 하다가 안받아져서 확인해 봤더니 /2015/09/05 날짜로 바뀐게 발견되었다. 그렇다면 그 부분까지 정규표현식으로 바꿔주면 된다.

s/(https:\/\/www\.avsnoop\.com\/files\/2015\/09\/[0-9]+\/[^/]*\.)(png|jpg)/\
\1\2\
/g

awk 명령어는 굳이 안써도 될꺼 같은데 습관처럼 썼다. white space 을 구별지어서 조작하는 명령을 줄 수있다. '{print $1}' 이면 첫번째 컬럼을 출력하라는 구문이다.

while 문은 전에 구별된 (여기 예제에서는 www.avsnoop 으로 구분된 이미지 주소) 를 url 로 받아온다. 그리고 printf 문을 이용해서 저장될 파일이름을 FILENAME 에 저장시키고 sed 문을 또 이용해서 확장자를 지정해준다.

downloading.. ${url} 로 현재 어떤 이미지를 다운 받는지 알려주고 정해진 파일 이름으로 curl 을 이용해서 다운받는다.

curl 을 사용하는 이유는 wget 으로 안받아지는 것들이 받아지기 때문이다. 즉 curl 이 wget 의 상위 호환이라고 보면됨. 최근 curl 을 사용하는게 이유가 있어서 이다. 이제 wget 을 보낼때가 됐다.


EmacsW32 를 설치하고 grep-find 를 동작하게 만들기 위해서 몇가지 세팅을 해줘야 합니다. 

1. EmacsW32 설치하기 


 EmacsW32 는 GNU Emacs 에다가 윈도에서 사용하기 편하게 몇가지 패치를 한 버젼입니다. 편해서 윈도에서는 항상 설치해서 사용하고 있습니다. 


2. grep-find 문제 해결 

 grep-find (find-grep 으로 써도 똑같이 동작함)은 현재 디렉토리부터 하위 디렉토리까지 찾고자 하는 단어를 포함하고 있는 줄의 정보를 표시하는 Emacs 의 기능입니다. 유닉스 명령어 (unix command) 중에서 가장 많이 쓰이는 find 와 grep 을 합쳐놓은 것입니다. 게다가 검색된 파일을 바로 emacs 상에서 열어서 편집할 수가 있습니다. 

요즘 대부분의 통합개발툴 (IDE) 상에서 지원하는 검색하고 무엇이 다르냐? 라고 물으면 '똑같다. 다른게 없다' 라고 말씀드릴 수 있습니다. 다만 아주 예전부터 지원하는 기능이라서 이 기능 때문에 이맥스( Emacs) 를 20년간 사용하고 있다는 분도 계십니다. 

grep 문법을 그대로 활용되니 찾고자 하는 단어를 정규 표현식으로 찾을 수 있습니다. 

하지만 EmacsW32 를 설치하고 바로 

M-x grep-find 

하고 나면 

  
   M-x grep-find 하면
      grep -r <C> -nH -e . --include=
      /bin/sh: C: No such file or directory
      
      Grep finished with no matches found at 날짜

      또는
      find . -type f -exec grep -nH -e  {} NUL ;
      find: missing argument to `-exec'
      
      Grep finished with no matches found at 날짜

      또는
      find . -type f -print0 | xargs -0 -e grep -nH -e 
      grep: unrecognized option `--color=auto'
      Usage: grep [OPTION]... PATTERN [FILE]...
      Try `grep --help' for more information.
      
      Grep exited abnormally with code 123 at 날짜

이렇게 나오고 안되실 것입니다.  제 경우에는 붉은색으로 나오면서 안 됐습니다. 

그래서 KLDP에서 참조 한 내용을 적어주자면 


2-1 . Emacs 상에서 다음 명령 실행 



      M-x customize-group
      grep




 2-2 .  Grep Highlight Matches 설정 


      Grep Highlight Matches: Value Menu 버튼 누르고 "Not Set"로 변경  state 버튼 누르고 Save for Future Sessions 을 선택해 줍니다.  

2-3 . Grep Find Use Grep R 설정 


      Grep Find Use Grep R: Toggle 버튼 누르고 "off (nil)"로 변경
      state 버튼 누르고 Save for Future Sessions 를 역시 선택해 줍니다. 
      

2-4. DotEmacs (.emacs ) 에서 확인 

  
   (custom-set-variables
      ;; custom-set-variables was added by Custom.
      ;; If you edit it by hand, you could mess it up, so be careful.
      ;; Your init file should contain only one such instance.
      ;; If there is more than one, they won't work right.

      '(grep-find-use-grep-r nil)
      '(grep-highlight-matches nil)
    

의 내용이 추가되어 있는 것을 확인해 줍니다. 

여기까지 하고 테스트 해주면 일단 하위 디렉토리가 없는 경우에서는 제대로 동작합니다. 하지만 하위 디렉토리가 존재하는 경우라면 

      xargs : cannot fork 

에러가 발생하면서 제대로 동작하지 않는 것을 목격합니다. 참고로 저는 MingW 같은것을 설치 안한 순수한 Windows7 환경입니다. 


3. w32shell-shell 설정해 주기 

메뉴상에서 

"Options" -  "Customize EmacsW32" 

를 선택해 줍니다. 그리고 그중에서 w32shell-shell 메뉴를 찾아서 다음 그림과 같이 "Windows cmd.exe" 로 선택해 줍니다. 그리고  "Save for future sessions" 를 클릭해 줍니다. 



자 또 DotEmacs (.emacs) 파일에서 다음과 같이 설정되어 있는지 확인 해 줍니다. 


      (custom-set-variables
      ...  
      '(w32shell-shell (quote cmd))
      ...)



이제 편하게 grep-find (find-grep) 을 사용하시면 됩니다. 



제가 무식한 탓인지 저는 리눅스의 가장 기초적인 쉘을 잘 못 씁니다.
편리한 툴에만 익숙해져 있기 때문입니다. (그렇다고 쉘이 편하지 않다는게 아닙니다!!)

유닉스 친구계열들을 보면 환경변수에 값들을 등록시켜서 쓰는데 그 문법이

crazia>NAME=crazia
crazia>export NAME

식으로 등록합니다. 이걸 편하게 하기 위해서 shell 로 여러가지 환경 변수를 등록시키기 위해서 shell 로 작성을 합니다.

#!/bin/bash

export NAME=crazia
export HOBBY=game
export HOBBY2=sleep

이 shell 을 my.sh 라고 작성해서 실행 옵션을 줘서 실행시키면 아무 동작을 안합니다.

결국 이거저거 시도하다가 알아낸 방법은
source ./my.sh 라고 해주면 바로 적용이 됩니다.

이 글은 나중에라도 혹시 또 명령어를 까 먹을까봐 글을 남기는 것입니다 ^^;

+ Recent posts