'Programming/Shell script'에 해당되는 글 9건

  1. 2014.05.20 mplayer 이어서 보기 스크립트. 2
  2. 2012.10.19 간단하지만 유용한 쉘스크립트. 2
  3. 2011.06.23 외부접속 확인하는 간단한 스크립트
  4. 2010.06.20 Screenlet 에 현재 재생중인 음악파일 커버 출력시키기 6
  5. 2009.01.28 mplayer 백그라운드 실행법 3

mplayer 이어서 보기 스크립트.

몇일동안 써 봤는데 별 문제는 없네요.


(뭐 생기면 고치면 되고...)


원리를 간단하게 설명하자면.


1,mplayer를 터미널상에서 재생시키면, 현재 재생중인 위치가 가장 마지막 위치에 나옵니다.


2, 재생전에 로그파일에 정보가 있는지 확인하고, 있으면 그곳을 시작위치로 저장해서 mplayer를 재생.


3, 이후 계속 출력 메세지를 받아놓고,


4, mplayer가 종료되면 로그의 가장 마지막줄을 읽어서 끝난 위치를 알아내는 거죠.


5, 그리고 난 다음, 로그파일에 정보가 없으면 새로운 로그 라인에 (기록초, 파일경로) 추가, 있으면 수정합니다.


(사실 원래는 중간에 메세지를 가로채서 파이프로 보내려고 했습니다만, 아무래도 뻘짓같아서...  포기하고 있다가 AUR에 mplayer-resumer(https://aur.archlinux.org/packages/mplayer-resumer/) 패키지를 보고 힌트를 얻어서 작성. (대체 왜 나는 쓸데없이 복잡한 방법을 생각해 냈을까?)


동영상 길이도 검사해서 맨뒷부분에서 exit시에는 기록을 하지 않게 만들어 놓았습니다.


저는 mplayer를 slave mode(외부에서 파이프로 mplayer 제어) 로도 사용하기 때문에 파이프를 설정하는 옵션도 들어갔습니다만, 필요없으면 없애주세요.


길이만 길다뿐이지 별거 아닙니다. 그럼 코드.


#!/bin/bash


# 필요 패키지 : bash, mplayer, ffmpeg, perl, 기타 쉘 관련 유틸리티
MPLAYER_PATH="/home/lowid/bin/mplayer"
MPLAYER_PIPE_PATH="/tmp/mplayer_pipe"
MPLAYER_LOG_FILEPATH="/share/ani/.mplayer_position.log"

# 키 후킹법 => 실패.
#while [ 1 ];do read -n 1 CMD >/dev/null;HEX="$(echo -n "$CMD" | hexdump -e \"%d\")";echo "key_down_event $HEX" > /tmp/mplayer_pipe;done
export MPLAYER_STATUS_OK_END=0
export MPLAYER_STATUS_OK_PLAYING=1
export MPLAYER_ERROR_NOT_PLAY_FILE=2
export MPLAYER_ERROR_LOG_POSITION_GET=3
export MPLAYER_ERROR_PLAYING=4

# mplayer에서 재생할 파일경로와 옵션을 분리해 냅니다
# 주의 : 각 인자를 확장자를 기준으로 분류합니다. (파싱 오류 가능성 있음!)
function Option_Parse()
{
    local Param=""
    unset OPTION_PARSE_RETURN_FILEPATH
    unset OPTION_PARSE_RETURN_OPTIONS

    for Param in "$@";do
        if [ "$(echo "$Param" | grep -E "\.mpg|\.wvx|\.rmvb|\.avi|\.mkv|\.wmv|\.mp4")" ];then

            OPTION_PARSE_RETURN_FILEPATH="$(realpath "$Param")"
        else
            OPTION_PARSE_RETURN_OPTIONS=""$OPTION_PARSE_RETURN_OPTIONS" "$Param""
        fi
    done
}

function Mplayer_Play_Duration()
{
    local Play_filepath="$1"
    local Play_file_duration=""
    local Hour=0
    local Minute=0
    local Second=""
    unset MPLAYER_PLAY_DURATION_RETURN_SECOND

    if [ ! -f "$Play_filepath" ];then
        return 1
    fi

    Play_file_duration="$(ffmpeg -i "$Play_filepath" 2>&1 | grep '^\s*Duration: [0-9][0-9]:[0-9][0-9]:[0-9][0-9]' | perl -pe 's/^.*?\: //g,s/\..*$//g')"
    Hour="$(echo "$Play_file_duration"   | cut -d ':' -f1 | perl -pe 's/^0//g')"
    Minute="$(echo "$Play_file_duration" | cut -d ':' -f2 | perl -pe 's/^0//g')"
    Second="$(echo "$Play_file_duration" | cut -d ':' -f3 | perl -pe 's/^0//g')"

    MPLAYER_PLAY_DURATION_RETURN_SECOND=$(($Hour * 60 * 60 + $Minute * 60 + $Second))

    return 0
}

function Mplayer_Log_Position_Get()
{
    local Play_filepath="$1"
    local Log_filepath="$2"
    local Log_play_file_line=""
    MPLAYER_POSITION_GET_RETURN_PLAY_SECOND=0

    if [ ! -f "$Play_filepath" ];then
        return 1
    fi

    if [ ! -f "$Log_filepath" ];then
        touch "$Log_filepath"
    fi

    Log_play_file_line="$(fgrep -n "$Play_filepath" "$Log_filepath" | cut -d ':' -f1 2>/dev/null)"
   
    if [ -n "$Log_play_file_line" ];then
        MPLAYER_POSITION_GET_RETURN_PLAY_SECOND="$(sed -n "$Log_play_file_line"'p' "$Log_filepath" | cut -d ' ' -f1)"
    fi

    return 0
}

function Mplayer_Log_Position_Set()
{
    local Play_filepath="$1"
    local Play_second="$2"
    local Log_filepath="$3"
    local Log_play_file_line=""
    local Log_play_file_data=""
    local Temp_filepath="/tmp/mpp_$RANDOM"

    if [ ! -f "$Play_filepath" ];then
        return 1
    fi

    if [ -z "$Play_second" ];then
        return 2
    fi

    if [ ! -f "$Log_filepath" ];then
        return 3
    fi

    Log_play_file_line="$(fgrep -n "$Play_filepath" "$Log_filepath" | cut -d ':' -f1 2>/dev/null)"
   
    # 없으면 뒤에 쓰고, 없으면 치환.
    if [ -z "$Log_play_file_line" ];then
        echo "$Play_second" "$Play_filepath" >> "$Log_filepath"
    else
        Log_play_file_data=""$Log_play_file_line"c "$Play_second" "$Play_filepath""
        sed -e "$Log_play_file_data" "$Log_filepath" > "$Temp_filepath"
        mv -f "$Temp_filepath" "$Log_filepath" 2>/dev/null
    fi

    return 0
}

function Mplayer_Log_Position_Delete()
{
    local Play_filepath="$1"
    local Log_filepath="$2"
    local Log_play_file_line=""
    local Temp_filepath="/tmp/mpp_$RANDOM"

    if [ ! -f "$Play_filepath" ];then
        return 1
    fi

    if [ ! -f "$Log_filepath" ];then
        return 2
    fi

    Log_play_file_line="$(fgrep -n "$Play_filepath" "$Log_filepath" | cut -d ':' -f1 2>/dev/null)"

    if [ -z "$Log_play_file_line" ];then
        return 3
    fi

    sed -e "$Log_play_file_line"'d' "$Log_filepath" > "$Temp_filepath"
    mv -f "$Temp_filepath" "$Log_filepath" 2>/dev/null

    return 0
}

function Mplayer_Play_Continue()
{
    local Options="$1"
    local Play_filepath="$2"
    local Play_position_second="$3"
    local Play_backward_second="$4"
    local Mplayer_end_second=""
    local Mplayer_start_position_second=""
    unset MPLAYER_PLAY_RETURN_POSITION

    if [ ! -f "$Play_filepath" ];then
        return 1
    fi

    if [ -z "$Play_position_second" ];then
        return 2
    fi

    if [ -z "$Play_backward_second" ];then
        return 3
    fi

    # mplayer 경로는 전역임 주의, -ss옵션에 0이 들어가도 상관 없다
    Mplayer_end_second="$("$MPLAYER_PATH" $Options -ss "$Play_position_second" "$Play_filepath" 2>/dev/null | strings | tail -2 | egrep '^A:' | perl -pe 's/^A:\s*//g,s/ V:.*//g')"

    if [ -z "$Mplayer_end_second" ];then
        return 4
    fi

    Mplayer_start_position_second="$(echo "$Mplayer_end_second" | cut -d '.' -f1)"
    if [ -z "$Mplayer_start_position_second" ];then
        return 5
    fi

    MPLAYER_PLAY_RETURN_POSITION="$(($Mplayer_start_position_second - $Play_backward_second))"
}

function Mplayer_Pipe()
{
    local Play_filepath="$1"
    local Pipe_path="$2"
    local Pipe_option=""
    unset MPLAYER_PIPE_RETURN_OPTION

    # mkv는 fifo 사용이 불가능한듯함
    if [ -z "$(echo "$Play_filepath" | grep \.mkv)" ];then
        if [ "$(file "$Pipe_path" | cut -d ' ' -f2)" != "fifo" ];then
            mkfifo "$Pipe_path"
        fi

        Pipe_option="-slave -input file="$Pipe_path""
    fi

    MPLAYER_PIPE_RETURN_OPTION="$Pipe_option"
}

function Mplayer()
{
    local Play_filepath=""
    local Options=""
    local Played_position_second=""
    local Restart_backword_second=2
    local Playing_position_second=""
    local Playing_file_duration=""
    local Restart_last_second=10
    local Return_succeed_value=0

    Option_Parse "$@"
    Play_filepath="$OPTION_PARSE_RETURN_FILEPATH"
    Options="$OPTION_PARSE_RETURN_OPTIONS"

    if [ -z "$Play_filepath" ];then
        return $MPLAYER_ERROR_NOT_PLAY_FILE
    fi

    Mplayer_Pipe "$Play_filepath" "$MPLAYER_PIPE_PATH"
    Options=""$Options" "$MPLAYER_PIPE_RETURN_OPTION""

    Mplayer_Log_Position_Get "$Play_filepath" "$MPLAYER_LOG_FILEPATH"
    if [ $? != 0 ];then
        return $MPLAYER_ERROR_LOG_POSITION_GET
    fi

    Played_position_second="$MPLAYER_POSITION_GET_RETURN_PLAY_SECOND"

    Mplayer_Play_Continue "$Options" "$Play_filepath" "$Played_position_second" "$Restart_backword_second"
    if [ $? != 0 ];then
        return $MPLAYER_ERROR_PLAYING
    fi

    Playing_position_second="$MPLAYER_PLAY_RETURN_POSITION"

    # 동영상의 재생 길이를 알때에만 기록을 한다.
    Mplayer_Play_Duration "$Play_filepath"
    if [ $? = 0 ];then
        Playing_file_duration="$MPLAYER_PLAY_DURATION_RETURN_SECOND"

        if [ $(($Playing_position_second + $Restart_last_second )) -lt "$Playing_file_duration" ];then
            Mplayer_Log_Position_Set "$Play_filepath" "$Playing_position_second" "$MPLAYER_LOG_FILEPATH"
            Return_succeed_value=$MPLAYER_STATUS_OK_PLAYING
        else
            Mplayer_Log_Position_Delete "$Play_filepath" "$MPLAYER_LOG_FILEPATH"
            Return_succeed_value=$MPLAYER_STATUS_OK_END
        fi
    fi

    return $Return_succeed_value
}


따로 설정할수 있는 부분은 전역으로 빼놨으니까 수정하시기 편할거에요.


ps; ~/.bashrc에 다음과 같이 쓰시길 추천. 아니면 따로 빼서 쓰시던지요.

alias mp='. /path/Mplayer.sh;Mplayer'




간단하지만 유용한 쉘스크립트.

엄청나게 간단하지만, 꽤 쓸만한 녀석들 모음입니다.


소스는 하도 간단해서 별로 설명할것도 없네요...


첫번째 스트립트는 터미널 영한사전처럼 간단하게(앞부분만) 위키 내용을 보여주는것.


다음 상황에서 문제가 발생하긴 해요...


1, 동의어가 발생했을때

(뭐, 이럴경우는 그냥 웹브라우저로 연결해서 보면 되긴 합니다)

2, 느리다. 특히 데이터가 많은 페이지일 경우...

(모바일페이지를 read하면 속도 향상이 있긴하겠지만, 귀찮아서...)

3, 사전에 단어가 별로 없다

(위키백과라고 해도, 단어수만 따지자면 백과사전(책)에 비해서 단어수가 후달려서 그런지 검색안되는 단어가 좀 있습니다)


[~/bin/script]$ cat wikipedia_ko.sh

#!/bin/bash

# 위키페이지는 공백대신 언더바를 쓴다
PAGE_NAME="$(echo "$*" | tr -s ' ' '_')"
LINK="http://ko.wikipedia.org/wiki/"$PAGE_NAME""
LINK_LIST_FILEPATH='/tmp/wiki_page'
BROWSER='firefox'
WIDTH=100

clear
echo '페이지 다운로드중 잠시만 기다려 주세요.'
wget "$LINK" -O "$LINK_LIST_FILEPATH" -q
clear

RESULT_DATA="$(cat "$LINK_LIST_FILEPATH" | egrep '<p>.*?<b>' | grep -v ^\\[ | head -1 | tr -d '\t' | perl -pe s/\<.*?\>//g | fmt -w "$WIDTH")"
if [ -n "$RESULT_DATA" ];then
    echo "$RESULT_DATA"
    echo
    echo "URL : "$LINK""
    echo -n '웹 브라우저에서 보시려면 <<v>> 키를 눌러주세요.'
    read -n 1 CHECKER
    echo
    if [ "$CHECKER" = 'v' ];then
        "$BROWSER" "$LINK" 1>/dev/null 2>/dev/null &
    fi
fi

rm -rf "$LINK_LIST_FILEPATH"



두번째 스크립트는 검색어/지도에서위치를 검색하는 역활을 하는겁니다.


구조는 더 간단합니다. 걍 url에 쿼리날리면 끝.


구글이나 네이버말고 다른 url query를 알면 그냥 붙여넣기 해서 쓰면 되겠죠...


일단 저는 아는게 2개밖에 없어서 일단 이렇게 만들어 봤어요.


[~/bin/script]$ cat direct_url.sh 

#!/bin/bash

BROWSER='firefox'

GOOGLE_FELLING_LUCKY_URL="http://www.google.com/search?ie=utf8&lr=lang_ko&btnI=&q="
NAVER_MAP_URL='http://map.naver.com/?query='
BASE_URL=""

while getopts 'g:m:' Option;do
    case $Option in
        g )
            BASE_URL="$GOOGLE_FELLING_LUCKY_URL"
            PARAM="$OPTARG"
            ;;
        m )
            BASE_URL="$NAVER_MAP_URL"
            PARAM="$OPTARG"
            ;;

        * )
            echo 'Usage >'
            echo ""$0" -g Query String : Google Feeling Lucky를 이용해 다이렉트 점프!"
            echo ""$0" -m Query String : Naver Map을 이용해서 주변을 검색합니다"
            ;;
    esac
done

"$BROWSER" "$BASE_URL""$PARAM" 1>/dev/null 2>/dev/null &


alias에서 터미널에서 바로 검색하면 정말 편하더군여

$go 네이버 메일

이런식으로 하면 LastPass랑 연동되서 바로 이메일 확인도 할수 있고...


$map 구청

이러면 집주변의 구청위치도 알수 있고...


여튼 일일이 브라우저 열어서 검색하고 귀찮게 안하고 명령어 한줄로 끝낼 수 있다는게 굉장이 편리해요...


ps; 네이버 open API를 사용하면 인기검색어 뷰어같은 괴상망측(...)한것도 만들수 있습니다..

http://dev.naver.com/openapi/apis/search/rank

저도 만들긴 했는데 별 쓸모는 없더군요... 그냥 심심했을때 한번 쳐보는 거 정도...


이외에도 많이 있긴한데, 나머지는 xml 파싱하는 스크립트도 넣어야 해서 귀찮아서 그냥 이정도로.

외부접속 확인하는 간단한 스크립트


ssh로 로긴해서 들어갔을때에도 무식하게 X를 당당히 띄어버리는 문제 발생.

그래서 아래 스크립트를 작성하여 일단 문젠 봉합해둠.

이하, 현재 쉘이 외부에서 접속했는지 확인하는 간단한 스크립트

#!/bin/bash
pts_id="pts/$(basename $(tty))"

# 쓸데없는 기교 (...)
if [ -n "$(who | grep -E ^"$USER"'.*'$pts_id'.*\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\)$')" ];then
    echo "외부접속"
fi

일단은 잘 작동하는거 같은데... 함 두고보자.

Screenlet 에 현재 재생중인 음악파일 커버 출력시키기

저번에 한번 conky자체에 그림나오는 기능을 사용해서 자켓 이미지를 출력하게 시도한 적이 있었다는..

http://lowid.tistory.com/entry/conky-%EA%B7%B8%EB%A6%BC

그런데 그때는... cpu를 너무 많이 먹는 바람에 하루정도 돌리고 포기...

그러다가 새로운  desklet을 한번 알게 되었는데 그게 바로 screenlet

이것을 좀 보니깐 python스크립트로 되어있는거라.. 좀 깨름직했지만...

(개인적으로  pstree 했을때 python 실행파일이 보이는것이 영 내키지 않아서)

그래도 어짜피 메모리 많이 남으니깐..

(전체 2긱인데 vm, firefox를 안돌리면 절대 200mb(각하의 100배임) 을 넘길일이 없으니)

그냥 쓰기로 해따.. 뭐 많은데 쓰지뭐

어쨋던 그렇게 하고.. screenlet 에 어떤 위젯(?) 이 있나 보니깐..

"SlideShow" 라는게 있어서 좀 살펴보니깐, 특정 디렉토리에 있는 그림파일을 출력해 주는 기능이 있었다는.

사용자 삽입 이미지

(Terminal lyrics, Slideshow, conky의 조화!!)

그래서 생각한게... 뭐 그냥 그 디렉토리에다가 현재 mpd로 재생중인 파일의 path을 알아내서

find로 찾아주면 간단하겠네.... 라는 생각이 들어서 바로 만들어 봤다..

find할때 재대로 안되는건 쿼우팅이 문제라서 따옴표를 붙여주고...

디렉토리 이름에 공백문자가 들어가서 생기는 문제는 IFS로 해결했다.

이러니깐 어지간한건 다 잡는듯.....

다음은 스크립트

#!/bin/bash

# MPD 설정 디렉토리
MPD_DIR="/data/mp3"

# 현재 재생중인 파일의 MPD 디렉토리
MPD_PATH=$(dirname "$(mpc -f "%file%" | head -n 1)")

# 자켓이 임시 복사될 디렉토리
JACKET_DIR="/home/lowid/etc/mpd_jacket"

# 현재 재생중인 파일의 디렉토리
PLAY_FILE_DIR="$MPD_DIR"/"$MPD_PATH"

# 경로에서 확장자가 jpg인것을 검색(작은따옴표 주의)
JACKET_FILES="$(find "$PLAY_FILE_DIR" -iname '*.jpg' -o -iname '*.png' -o -iname '*.gif')"

# 아까 있던 파일들 모두 삭제
rm -rf "$JACKET_DIR"/*

# IFS를 '\n'으로 변경(spc 방지)
IFS='
'

# 복사
for IMAGE_FILE in $JACKET_FILES
do
    echo "$IMAGE_FILE"
    cp "$IMAGE_FILE" "$JACKET_DIR"
done

그리고 이걸 곡이 바뀔때 마다 실행해 주면 된다 -_-..

나는 그냥 귀차나서 lyrics프로그램 내부에 mpd감지하는 루틴에

system("/home/lowid/bin/mpd_jacket.sh");

넣어버림 ㅋㅋㅋㅋㅋㅋㅋ


이래도 문제는 발생한다는거...

곡이 바뀌면서 바로 커버가 바뀌는게 아니라 몇초 딜레이 시간이 필요하다. (머 1초로 설정하면 거의 없긴해두)

(SlideShow의 자체 갱신 시간이 있기때문)

python 프로그램을 찾아서 갱신시간을 event로 알아낼수 있게 어떻게 수정하면 되긴하겠는데...

python 은 귀찮기도 하고............ 걍 PASS 귀차늠..

아니 윗에처럼 하느니.. 그냥 lyrics + cover + control이 되는 새로운 프로그램을 gtk로 만드는게 나을지도

근데 이것도 귀찮아서 아마 시도도 안할거임 아마..............

추가-----

find에서 exec로 해도 되는거 같은데 .;

mplayer 백그라운드 실행법

그냥 mplayer filepath & 이렇게 하면 백그라운드로 되긴하는데(이론상으론 그렇...)

mplayer의 프로세스 상태가  stop이 되어버린다 

(영상이 안나온다 - )

하지만 그렇게 안하고 영상도 나오면서 백그라운드로 만들수 있다

mplayer filepath >/dev/null</dev/null &

(뭃론 표준출력이 나오게 하길 원한다면 "> /dev/null" 을 빼도 상관이 없긴하다)

이걸좀 응용하면

mplayer filepath &>/dev/null</dev/null &;sleep 2;killall mplayer

이런것도 가능하다 (물론 killall 보다 process id 로 죽이는게 더 낫겠지만)

구글링하면 바로 메일링리스트가 떠서 쉽게 찾을수 있지만

혹시해서  적어두었다

출저:  http://lists.mplayerhq.hu/pipermail/mplayer-users/2003-December/041327.html



하루라도 쓸데없는 뻘글을 써보려고 노력중.,........
prev 1 2 next