Skip to content

Bash:Example

Bash의 간단한 사용방법을 정리한다.

Categories

Debugging

Bash의 디버깅방법은 아래와 같다.

set -x
## OR
set -v

## 원상복구
set -

root 권한 확인

root 권한 강제:

if [[ $(id -u) -ne 0 ]]; then
    echo 'Please run as root.'
    exit 1
fi

root 권한 불가:

if [[ $(id -u) -eq 0 ]]; then
    echo 'Please do not run as root.'
    exit 1
fi

Check if sudo

if [ "$(whoami)" != "root" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

or

## $(id -u) == $EUID
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

Index Rename

IDX=0; for i in *.jpg; do mv "$i" "${IDX}.jpg"; let "IDX = IDX + 1"; done

리눅스 배포판 검사

lsb_release -r | awk '{print $2}'

또는 다음과 같이 확인한다.

cat /etc/*-release | grep -E '^ *NAME *='

lsb_release 명령 참조.

Disable beep sound

echo 'set bell-style none' >> ~/.inputrc

또는 /etc/profile파일을 열어 다음 줄 추가.

echo -ne '\033[11;0]'

#!

Whereis

특정 파일의 전체경로를 찾고 싶은 경우 아래와 같이 입력한다.

which sh

참고로 cmd에서 동일한 동작을 하는 코드는 아래와 같다.

where sh

사용자 입력

아래와 같이 사용자 입력을 받을 수 있다.

# USER_TEMP 변수에 사용자 입력값을 적용한다.
read USER_TEMP

# 1 글자만 입력 받는다.
read -n 1 USER_TEMP

# 미리 문자열을 출력한다.
read -p "Repository username: " USER_TEMP

# 보안속성을 추가한다. (사용자 입력이 출력되지 않는다)
read -s -p "Repository password: " USER_TEMP

참고로 아래와 같이 YES/NO를 확인할 수 있다.

read -p "Do you wish to install this program?" yn
case $yn in
    [Yy]* ) make install; break;;
    [Nn]* ) exit;;
    * ) echo "Please answer yes or no.";;
esac

변수명을 인자로 사용하는 방법 (${!param})

variable=255.255.255.255
param=$1
echo ${!param}

then execute:

bash script.sh variable
255.255.255.255

Command-line user input

스크립트 등을 사용하여 명령행으로 사용자 입력을 넘기고 싶을 경우가 있다.

우선 아래와 같은 파일이 있을 경우:

# test.sh
$ read value
$ echo '1: ' $value
$ read value
$ echo '2: ' $value
$ read value
$ echo '3: ' $value

아래와 같이 사용하면 된다.

$ echo -e 'a\nb\nc' | ./test.sh

How to iterate over arguments

INDEX=1
SIZE=$#
while [[ $INDEX -le $SIZE ]]; do
    echo $1
    let 'INDEX = INDEX + 1'
    shift
done

The eval builtin command

직접 Bash 명령을 입력하고 싶을 경우 eval명령을 사용하면 된다.

$ eval "export NAME='VALUE'"

PIP를 통한 입력 LOOP

PIP를 통하여 입력루프를 아래와 같이 줄 수 있다.

command | while read -r line; do
  command "$line"
done

EXIT CODE 확인

최종 EXIT CODE는 아래와 같이 확인할 수 있다.

$ echo $?

존재유무(Exist)에 따른 코드

To check if a directory exists in a bash shell script you can use the following:

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

# Or to check if a directory doesn't exist:
if [ ! -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY doesn't exist
fi

# In Cshell:
if ( ! -e $DIRECTORY ) then
    # Will enter here if $DIRECTORY doesn't exist
endif

# check if a file doesn't exist:
if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi

스크립트 내용 출력하기 (디버깅)

디버깅을 위하여 set -x를 설정하면 스크립트 내용이 모두 출력된다. 디버깅 여부를 출력하고 싶은 경우 아래와 같이 확인할 수 있다.

if [[ "$-" == *x* ]]; then
  echo "is set"
else
  echo "is not set"
fi

한 줄을 모두 "-"로 채우기

COLUMNS 변수 값을 가져와서 터미널 너비를 감지한다. (해당 변수가 없다면 tput 를 사용한다.)

cols=${COLUMNS:-$(tput cols)}

## "-"로 한 줄을 채웁니다.
printf -v line '%*s' "$cols" ''
echo "${line// /-}"

Expansion of variable inside single quotes

쿼우트 안에 환경 변수를 추가하는 방법은 아래와 같다.

'before'"$variable"'after'
'before'\''after'
'before'"'"'after'

User defined function

function e {
    echo $1 
}

Platform checker

현재 사용하는 OS를 식별하고 싶을 경우 아래와 같이 사용하면 된다.

case "$(uname -s)" in
   Darwin)
     echo 'Mac OS X'
     ;;
   Linux)
     echo 'Linux'
     ;;
   CYGWIN*|MINGW32*|MSYS*)
     echo 'MS Windows'
     ;;
   *)
     echo 'other OS (or missing cases for above OSs)' 
     ;;
esac

Function object

함수객체는 아래와 같이 만들고 사용할 수 있다.

#!/bin/sh

function test1 {
    echo FUNCTION_TEST1
}
function test2 {
    echo FUNCTION_TEST2
}

declare -a VAL
VAL[0]=test1
VAL[1]=test2

function run {
    local index=$1
    ${VAL[$index]}
}

run 0
run 1

Date format

파일이름을 위한 현재 날짜 및 시간 포맷은 아래와 같다.

DATE_FORMAT=`date +%Y%m%d_%H-%M-%S`

STDOUT and STDERR

아래와 같이 STDERR에 대한 출력에 색상을 더할 수 있다.

function stdout { echo "$@" }
function stderr { echo -e "\033[31m$@\033[0m" 1>&2; }

stdout 'STDOUT Message'
stderr 'STDERR Message'

Current file

__FILE__="${BASH_SOURCE[0]}"
echo $__FILE__

Current directory

호출한 스크립트 파일의 상위 디렉토리 경로를 구하는 방법은 아래와 같다.

SCRIPT_DIR="$( cd "$(dirname ${BASH_SOURCE[0]})" ; pwd -P )"

참고로 위와 같이 사용할 경우 디렉토리 경로가 변경되므로 주의해야한다.

MD5 checksum result

MD5_CMD=`if [[ $(uname -s) == Darwin ]]; then echo 'md5 -r'; else echo 'md5sum'; fi`
CHECKSUM=`$MD5_CMD test_file_path | awk '{print($1);}'`

Upper and Lower

문법은 아래와 같다.

  • lower case: ${parameter,,pattern}
  • UPPER CASE: ${parameter^^pattern}
$ string="Hello, World!"
$ echo $string
Hello, World!
$ echo ${string,,}
hello, world!
$ echo ${string^^}
HELLO, WORLD!

How to obtain the number of CPUs/cores

## Darwin:
$ sysctl -n hw.ncpu

## Linux:
grep -c ^processor /proc/cpuinfo

## Windows:
$ echo $NUMBER_OF_PROCESSORS
## OR (winbatch):
$ WMIC CPU Get NumberOfLogicalProcessors

Split string loop

sentence="one;two;three"
sentence=${sentence//;/$'\n'}  # change the semicolons to white space
for word in $sentence
do
    echo "$word"
done

Find string

function findString {
    local string=$1
    local find=$2
    local size=${#string}

    for ((i = 0; i < $size; i++)); do
        if [[ "${string:$i:1}" == "$find" ]]; then
            break;
        fi
    done
    echo $i
}

Reverse find string

function rfindString {
    local string=$1
    local find=$2
    local size=${#string}

    for ((i = $size; i >= 0; i--)); do
        if [[ "${string:$i:1}" == "$find" ]]; then
            break;
        fi
    done
    echo $i
}

참고로 탭(\t)과 같은 문자는 아래와 같이 사용하면 된다.

index=`findString $path $'\t'

File extension

파일의 확장자를 획득하는 방법은 아래와 같다. 위의 rfindString함수가 필요한다.

function getExtension {
    local name=$1
    local index=`rfindString $name '.'`
    echo ${name:$index}
}

더 간단한 방법은 여기를 참조.

Remove file list

특정 디렉토리(SRC_DIR)에 존재하는 파일이 대상 디렉토리(DEST_DIR)에 존재할 경우 제거하는 스크립트는 아래와 같다.

WORKING=$PWD
SRC_DIR=train_fire_backup/
DEST_DIR=train/

for path in $SRC_DIR*; do
    echo $path | sed "s;.*/;$DEST_DIR;g" | xargs rm
done

Rename file index

INDEX순서로 파일명을 변경하는 방법은 아래와 같다.

WORKING=$PWD
SRC_DIR=train/
DEST_DIR=train2/

if [[ ! -d "$DEST_DIR" ]]; then
    mkdir $DEST_DIR
fi

INDEX=0

for path in $SRC_DIR*.jpg; do
    let "INDEX = INDEX + 1"
    mv $path ${DEST_DIR}${INDEX}.jpg
done

Extract directory

현재 위치에 있는 모든 디렉토리를 개별적으로 압축한다.

for i in $(find . -type d -depth 1); do printf "%s\n%s\n" "$i.tar.gz" "$i" | xargs -n 2 tar czf; done

Dynamic variable names

var=name_of_var
echo $(eval echo "\$$var")

Multi-line string

여러줄로 문자열 값을 지정하는 방법

text="this is line one
this is line two
this is line three"
echo "$text" > filename

Piping command output to tee but also save exit code of command

mvn clean install $@ | tee $logfile
echo ${PIPESTATUS[0]}

Favorite site