아카이브 와 압축

아카이브 : 여러개의 파일이나 디렉터리를 모아서 파일 하나로 만드는 것

압축 : 파일의 크기를 줄이는 것

 

tar 명령어

괄호 확장 명령어 팁!

{시작숫자..끝숫자}

$ touch dir1/file-{1..5}.txt
$ ls dir1
file-1.txt file-2.txt file-3.txt file-4.txt file-5.txt

$ echo {a..e}.txt
a.txt b.txt c.txt d.txt e.txt

$ echo sample.{txt,log,dat}
sample.txt sample.log sample.dat

 

tar 사용방법

$ tar cf <아카이브 파일 이름> <아카이브로 묶을 파일 경로>

 - c : create

 - f : file

 - tar 에서 옵션을 지정할 때에 하이픈(-) 을 붙여도 되고 안 붙여도 된다.

 

아카이브 파일 만들기 ( cf )

$ tar cf dir1.tar dir1

 

아카이브한 파일 내용 확인하기 ( tf )

$ tar tf dir1.tar
dir1/
dir1/file-5.txt
dir1/file-4.txt
dir1/file-3.txt
dir1/file-2.txt
dir1/file-1.txt

 

아카이브 해제하기 ( xf )

$ rm -rf dir1
$ tar xf dir1.tar
$ ls dir1
dir1/file-5.txt
dir1/file-4.txt
dir1/file-3.txt
dir1/file-2.txt
dir1/file-1.txt

 

옵션 v

 

파일 작성시 사용 cvf  : 아카이브 대상이 되는 파일 목록을 출력

$ tar cvf dir1.tar dir1
a dir1
a dir1/file-5.txt
a dir1/file-4.txt
a dir1/file-3.txt
a dir1/file-2.txt
a dir1/file-1.txt

 

파일 내용 확인시 사용 tvf : ls -a 와 같이 파일의 상세 정보 출력

$ tar tvf dir1.tar
drwxr-xr-x  0 joey   staff       0  4 12 15:36 dir1/
-rw-r--r--  0 joey   staff       0  4 12 15:36 dir1/file-5.txt
-rw-r--r--  0 joey   staff       0  4 12 15:36 dir1/file-4.txt
-rw-r--r--  0 joey   staff       0  4 12 15:36 dir1/file-3.txt
-rw-r--r--  0 joey   staff       0  4 12 15:36 dir1/file-2.txt
-rw-r--r--  0 joey   staff       0  4 12 15:36 dir1/file-1.txt

 

※ tar 은 파일의 권한, 소유자, 타임스탬프 같은 파일의 속성을 유지 한채로 아카이브함

                → 슈퍼 사용자 권한으로 백업에 사용 가능

셸 스크립트 동작 방식

많은 파일 속에서 특정문자열을 검색

 

사용되는 명령어

xargs

- 표준 입력으로 인자의 리스트를 받는 명령어

- 주로 find,  grep 과 조합을 하여 많은 파일에서 문자열을 검색하는 용도로 사용

- xargs < 실행하고 싶은 명령어> 방식

- < 실행하고 싶은 명령어> 가 표준입력으로 전달 받은 리스트를 인자로 실행

$ find . -type f -name '*.txt' | xargs ls -l

 - txt 타입의 파일 목록을 출력 →  출력된 리스트를 인자로 받아 실행

 

스크립트 예시

#!/bin/bash

pattern=$1
find . -type f | xargs grep "$pattern" 

 

위의 스크립트의 단점은

- find 에서 한 개의 결과가 나오면 파일이 이름이 출력이 되지 않는 다는 점 →  H 옵션 필요

- 파일에서 "pattern" 을 찾은 위치를 알 수 없다는 점  → n 옵션 필요

 

#!/bin/bash

pattern=$1
find . -type f | xargs grep  -nH "$pattern" 

 

좀 더 개선을 해보자

이 스크립트를 매번 검색할 디렉터리로 가서 실행해야하는 불편 → 디렉터리 지정 추가

검색하는 파일의 타입이 고정되어 있다는 불편함 → 파일타입 지정 추가

 

findgrep.sh

#!/bin/bash

pattern=$1
directory=$2
filetype=$3

if [ -z "$directory" ]; then
   directory='.'
fi

if [ -z "$filetype" ]; then
  filetype'*'
fi

find "$directory"  -type f -name "$filetype" | xargs grep  -nH "$pattern" 

 

사용 예시

$ findgrep.sh ldk "home" '*.txt'

 

 

도움말 / 사용법 표시

아래 코드를 findgrep.sh 상단에 추가

usage()
{
    #  셸 스크립트의 파일 이름을 취득
    local script_name=$(basename "$0")
    
    #도움말 표시
    cat << END

    Usage : $ script_name PATTERN [PATH] [NAME_PATTERN]
    Find file in currernt directory recursively, and print lines which match PATTERN

        PATH                        find file in PATH directory, instead of current directory
        NAME_PATTERN    specify name pattern to find file

    Examples:
        $ script_name return
        $ script_name return ~ '*.txt'
   
    END
}

if [ "$#" -eq 0 ]; then
    usage
    exit 1
fi

.... 코드

 

- cat << : here document 라고 하여 여러 행의 텍스트를 셸 스크립트에서 그대로 기술 하고 싶을 때 사용

 

에러 표시

......

# 검색 디렉토리가 존재 하지 않을 때 에러 메세지 출력하고 종료
if [ ! -d "$directory" ]; then
    echo "$0: ${directory} : No such directory" 1>&2
    exit 2
fi

 

 

최종 파일

#!/bin/bash

# 사용 방법
usage()
{
    #  셸 스크립트의 파일 이름을 취득
    local script_name=$(basename "$0")
    
    #도움말 표시
    cat << END

    Usage : $ script_name PATTERN [PATH] [NAME_PATTERN]
    Find file in currernt directory recursively, and print lines which match PATTERN

        PATH                        find file in PATH directory, instead of current directory
        NAME_PATTERN    specify name pattern to find file

    Examples:
        $ script_name return
        $ script_name return ~ '*.txt'
   
    END
}

if [ "$#" -eq 0 ]; then
    usage
    exit 1
fi

# 검색 함수 
pattern=$1
directory=$2
filetype=$3

if [ -z "$directory" ]; then
   directory='.'
fi

if [ -z "$filetype" ]; then
  filetype'*'
fi

# 검색 디렉토리가 존재 하지 않을 때 에러 메세지 출력하고 종료
if [ ! -d "$directory" ]; then
    echo "$0: ${directory} : No such directory" 1>&2
    exit 2
fi

find "$directory"  -type f -name "$filetype" | xargs grep  -nH "$pattern" 

셸 스크립트 동작 방식

1.  지정한 디렉터리의 모든 파일과 디렉터리를 출력하는 셸 스크립트 작성

 

작성 팁

1. 먼저 작고 간단한 기능부터 구현

2. 전체적인 흐름을 먼저 작성한 뒤 조금씩 구현

 

#!/bin/bash

# 함수 정의: 주어진 경로에 대한 파일 및 디렉터리 목록을 재귀적으로 출력
list_recursive() {

     local filepath=$1        # 첫 번째 인자로 받은 파일 경로를 지역 변수에 저장
     local indent=$2         # 두 번째 인자로 받은 들여쓰기 값을 지역 변수에 저장
     
     # 들여쓰기를 적용하고 파일 이름만 추출하여 출력
     echo "${indent}${filepath##*/}"
     
     # filepath 가 디렉터리인지 확인합니다.
     # 디렉터리라면 그 안의 항목들에 대해 루프를 실행
     if [ -d "$filepath" ]; then
         
         local fname    # 현재 처리 중인 파일 또는 디렉터리의 이름을 저장할 지역 변수
         
         for fname in $(ls $filepath) # 디렉터리 내의 각 항목에 대해 반복
         do
              # fname 이 디렉터리라면 재귀적으로 list_recursive 를 호출          
              list_recursive "${filepath}/${fname}" "${indent} "
         done
     fi
}

# 스크립트 실행의 시작점: 첫 번째 인자로 받은 경로를 기준으로 함수를 호출
list_recursive "$1" ""

장점

  • 기존 명령어를 조합하여 새로운 명령어를 만들 수 있다.
  • 파이프라인과 리다이렉션 같은 셸의 기능과 셸 스크립트를 조합하여 다양한 문제를 해결할 수 있다.
  • 리눅스의 다양한 필터를 조합하여 문제를 해결하는 것 가능하다.
  • 반복되는 수작업을 줄일 수 있다.

 

단점

  • 대규모 시스템에 적합하지 않다.
    • 변수타입이 없다.
    • 객체 지향 프로그래밍 불가능
    • IDE 지원도 부족
  • 고성능이 필요한 처리
    • 기본적으로 한 행씩 명령어를 실행 ( 자식 프로세스를 생성하는 처리가 동반) → 속도가 느리다.

●  구조

# 방식 1
function <함수 이름> ()
{
     처리
}

# 방식 2
function <함수 이름>
{
     처리
}

# 방식 3
<함수 이름> ()
{
     처리
}

 

 

● 예시

func-example.sh

# !/bin/bash

homesize ()
{
    date
    du  -h  | tail -n 1
}

homesize

 

func-example2.sh

# !/bin/bash

print_parameters ()
{
    echo "\$1 = $1"
    echo "\$2 = $2"
    echo "\$3 = $3"
    echo "\$4 = $4"
    echo 
    echo "$# arguements"
    echo "script name  $0"
}

print_parameters   aaa bb ccc   # 함수 호출 + 인자 입력

● 셸 함수 종료상태 지정

   함수안에서 가장 마지막에 실행한 명령어의 종료상태가 셸 함수의 종료 상태

 

return < 종료상태>

#!/bin/bash

checkparam()
{
   if [ -z "$1"  ]; then
       return 1
   fi
   ls "$1"

 

+ Recent posts