bash script (backup)2021. 6. 8. 14:20

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/517067

 

특정 파일 또는 디렉토리가 존재하는지 확인하는 방법이다. 스크립트의 인자(argument)로 파일이나 디렉토리를 입력받았을 경우 인자의 유효성을 확인할 때 요긴하게 사용 가능.

우선 파일의 존재 여부를 확인해 보자. if 조건문에서 test 명령의 -e 옵션을 사용하면 된다. 아래의 예시를 참고하자.

 

file_name="my_file.txt"

# 파일이 있을 경우 메세지 출력

if test -e $file_name

then echo "$file_name 파일을 찾았습니다."

fi

 

# 파일이 없을 경우 메세지 출력(! 사용)

if ! test -e $file_name

then echo "$file_name 파일이 없습니다."

fi

 

디렉토리의 존재 여부는 -d 옵션을 사용하면 된다.

 

dir_name="/var/log/"

# 디렉토리가 있을 경우 메세지 출력

if test -d $dir_name

then echo "$dir_name 디렉토리를 찾았습니다."

fi

 

test 명령은 대괄호([ ])로 대체해서 쓸 수도 있다. 바로 위의 if 조건문 예시를 아래과 같이 써도 된다.

 

if [ -d $dir_name ]

then echo "$dir_name 디렉토리를 찾았습니다."

fi

 

대괄호를 사용할 때는 띄어쓰기에 주의하자. 대괄호 안의 표현과 대괄호 사이에 반드시 공백이 한칸 들어가야 한다.

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 5. 10. 15:36

 

반달가면 이글루에서 백업 - bahndal.egloos.com/514695

 

조금 생각해 보면 금방 알 수 있는 내용이긴 하지만, 최근 쇠퇴하고 있는 기억력을 절감하는 중이라 적어 두기로 했다.

grep 명령을 이용해서 특정 문자열을 검색하고 해당 문자열을 포함한 파일명을 찾는 자세한 방법은 이전에 올린 게시물을 참고하자.

 

일단 아래의 예시를 보자. -H 옵션을 사용하면 결과가 파일명:문자열 형태로 출력된다. -r(recursive) 옵션은 지정한 디렉토리와 그 하위 디렉토리에서 검색하기 위한 것이다.

# /home/john/Documents 디렉토리와 그 하위 디렉토리에서 abcd를 포함한 파일명과 해당 문자열을 출력
grep -Hr abcd /home/john/Documents

/home/john/Documents/my_file.txt:abcdefg

/home/john/Documents/my_file2.dat:abcde_xyz

 

다단계로 복잡한 검색을 하면서 파일명도 확인하려고 한다면, 일단 파일명을 확인하기 위한 -H 옵션으로 검색을 하고, 나머지 복잡한 검색을 파이프(|)를 이용해서 뒤쪽으로 이어주면 된다. 아래의 예시를 보자.

 

# abcd가 포함된 파일명과 해당 문자열을 검색한 후에 xyz가 포함된 항목을 제외(-v 옵션)

grep -Hr abcd /home/john/Documents | grep -v xyz

/home/john/Documents/my_file.txt:abcdefg

 

파이프 이후에는 -H 옵션이 의미가 없어진다. 입력이 파일이 아니라 이전 명령의 출력값이 되기 때문이다. 아래와 같이 사용하면 파일명을 확인할 수 없다.

 

# 이렇게 하면 파일명 확인 불가능

grep -r abcd /home/john/Documents | grep -H -v xyz

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 4. 16. 13:36

 

반달가면 이글루에서 백업 - bahndal.egloos.com/510895

 

한 문장에서 단어 구분자가 여러개인 경우에 단어를 하나씩 뽑아내는 방법니다. 예를 들어 "Hello, my name is John. What's yours?" 이런 문장이 있는데 여기서 단어를 하나씩 가져오려면, 단어 구분자가 공백/쉼표/마침표/물음표 이렇게 여러가지가 되기 때문에 cut 명령으로는 어렵고 awk 명령을 써야 한다.

awk의 -F 옵션을 이용해서 구분자(field separator)를 지정할 때 정규표현(regular expression)을 사용하면 되겠다. 아래의 예시를 보자.

# 구분자는 공백/쉼표/마침표/물음표, 첫번째($1)와 세번째($3) 항목을 출력하되 항목 사이에 콜론을 출력
echo "Hello, my name is John. What's yours?" | awk -F '[ ,.?]' '{print $1 ":" $3}'
Hello:my

-F 옵션에서 구분자를 대괄호([])로 묶으면, 대괄호 안에 있는 캐럭터들이 모두 구분자로 인식된다. awk에 적용되는 명령문을 shell에서 해석하지 않도록 하기 위해 작은 따옴표(')를 사용하고 있음에 유의.

위의 예에서 Hello 다음에 구분자에 속하는 쉼표와 공백이 연속해서 나왔기 때문에, 첫번째 항목은 Hello, 두번째 항목은 아무것도 없고(null), 세번째 항목은 my가 될 것이다.

또 다른 예로, 위의 문장으로부터 쉼표나 마침표 등을 제외하고 단어만 골라서 출력을 해 보자. awk에서 for 명령을 이용한다.

# 유효한 단어만 골라내서 출력, 구분자는 공백/쉼표/마침표/물음표
echo "Hello, my name is John. What's yours?" | awk -F '[ ,.?]' '{ for (i=1;i<=NF;i++) print $i }' | grep [[:alnum:]]
Hello
my
name
is
John
What's
yours

for문을 이용해서 1부터 NF까지 하나씩 증가시키면서 i번째 항목을 출력한 것이다. NF 변수는 awk에서 항목의 수(the number of fields)를 뜻한다. 구분자가 연속해 있을 경우 빈 줄이 출력되므로, 빈 줄은 빼고 유효한 단어만 골라내기 위해 grep 명령을 연결했다.

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 3. 30. 17:24

 

반달가면 이글루에서 백업 - bahndal.egloos.com/509465

 

파일은 그대로 놔두고 특정 디렉토리 하위에 있는 디렉토리 구조를 다른 디렉토리 하위에 복사하는 방법이다. find 명령을 사용해서 복사할 수 있다. (find 명령에 대한 소개는 이전 게시물을 참고하자. 여기로)

 

~/temp1/src 하위의 디렉토리 구조를 ~/temp2/dst 디렉토리로 복사하는 경우를 생각해 보자. 복사하고자 하는 원래 디렉토리로 간 후에 find 명령을 이용해서 디렉토리 구조를 출력하도록 한 후, -exec 옵션을 통해서 해당 출력물을 mkdir 명령의 인자(argument)로 대응시킨다.

cd ~/temp1/src
find ./ -type d -exec mkdir -p ~/temp2/dst/{} \;

find ./ -type d 명령에 의해 하위 디렉토리명을 찾은 후, 해당 결과에 대하여 -exec 옵션을 통해 mkdir 명령을 실행한다. mkdir 명령에서 {} 이 부분에 find의 결과가 인자로 들어가게 된다. -exec 옵션에 지정된 명령의 종료 지점을 표시하기 위해 세미콜론(;)을 사용하는데, 셸(shell)에서 명령어 구분자로 해석하는 것을 방지하기 위해 이스케이프(escape) 캐럭터인 역슬래시(\)로 보호해 준다.

참고로 mkdir 명령에 -p 옵션을 주면 필요할 경우 상위 디렉토리도 생성하라는 의미가 된다. 아래의 예시를 보자.

# ~/dir1 디렉토리가 없는 상태에서 실행할 경우 오류 발생
mkdir ~/dir1/dir2

# ~/dir1 디렉토리가 없다면 먼저 ~/dir1 디렉토리를 만든 후 dir2 디렉토리 생성(-p 옵션)
mkdir -p ~/dir1/dir2

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 3. 3. 15:37

 

반달가면 이글루에서 백업 - bahndal.egloos.com/508427

 

date 명령을 이용해서 파일을 마지막으로 수정한 날짜와 시간을 확인할 수 있다. -r 옵션을 사용한다. 아래의 예시를 보자.

 

date -r my_file.txt

2014. 07. 03. (목) 16:34:33 KST

 

원하는 항목만 골라내는 등 표시 형식을 바꿀 수도 있다. 아래의 예시를 보자.

 

# 연도만 구하기

date -r my_file.txt "+%Y"

2014

 

# 연도 및 날짜

date -r my_file.txt "+%Y%m%d"

20140703

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 2. 19. 16:36

 

반달가면 이글루에서 백업 - bahndal.egloos.com/503597

 

수 계산에 유용한 bc 명령을 이용하면 10진수를 2진수나 16진수로, 또는 그 반대로 변환할 수 있다. bc 명령에 대한 내용은 이전 게시물을 참고하자. 여기로 

 

일단 아래의 예시를 보자.

# 10진수를 2진수로 변환 (obase 변경)
echo "obase=2; 27" | bc
11011

bc에는 출력값과 입력값의 기수(base)를 설정하는 변수가 있는데, 각각 obase와 ibase이다. (기본적으로 10진수를 사용하므로 기본값은 둘 다 10이다.) obase 값을 2로 설정하면 출력값이 2진수로 표현된다. 반대로 2진수를 10진수로 변환하려면 ibase 값을 2로 설정하면 되겠다.

# 2진수를 10진수로 변환 (ibase 설정)
echo "ibase=2; 11011" | bc
27

# 2진수를 16진수로 변환
# obase 설정 이후 ibase 설정
echo "obase=16; ibase=2; 11011" | bc
1B

obase와 ibase를 둘 다 설정할 경우 obase 설정이 먼저 나와야 한다. 왜 그러냐 하면, 예를 들어 ibase를 먼저 2로 설정하면 그 다음에 obase를 설정할 때 입력할 값이 먼저 설정된 ibase 기준(즉 2진법)으로 되어야 하기 때문이다. 2진수를 16진수로 변환할 때 ibase를 먼저 설정하는 경우는 아래와 같이 좀 복잡해진다.

# 2진수를 16진수로 변환
# ibase 설정을 먼저 하는 경우
echo "ibase=2; obase=10000; 11011" | bc
1B

입력값의 기수를 정하는 ibase가 먼저 2진수로 설정되었기 때문에, obase를 16진수로 설정하려면 16을 2진수로 변환한 10000을 obase 값으로 설정해 주어야 한다. 복잡하다.

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 2. 9. 14:02

 

반달가면 이글루에서 백업 - bahndal.egloos.com/502461

 

연속적인 수를 생성해 주는 seq 명령에서 유용한 옵션들을 정리해 두기로.

일단 seq 명령에 대한 기본적인 내용은 이전 게시물을 참고하자. 여기로

 

아래의 예시들을 참고하자.

# 기본 명령: 2에서 4까지 생성하는 예시
seq 2 4
2
3
4

한줄에 하나씩 출력하지 않고 특정한 구분자(separator)를 사용하고 싶다면 -s 옵션을 이용하면 된다.

# 구분자를 콜론으로 변경: -s 옵션
seq -s ":" 2 5
2:3:4:5

 


구분자를 탭으로 변경하고 싶다면 echo 명령에서 -e 옵션을 사용.  따옴표에 유의하자. echo 부분을 역따옴표(`)로 감싼 후 이것을 다시 따옴표(")로 감싸주어야 한다.

# 구분자를 탭으로 변경
seq -s "`echo -e '\t'`" 2 5
2    3    4    5

 

출력값의 자리수를 맞추고 싶다면 -w 옵션을 사용하면 된다. 가장 긴 출력의 자리수에 맞춰서 앞에 0을 추가해 준다. 아래의 예시를 보자.

# 자리수 맞춤
seq -w 8 10
08
09
10

# 9에서 10까지 0.5 간격으로
seq -w 9 0.5 10
09.0
09.5
10.0

출력 형식을 정하고 싶다면 -f 옵션을 사용. -f 옵션과 -w 옵션은 같이 사용할 수 없으며 둘 중 하나만 사용해야 한다. -f 옵션에서는 C언어의 printf 형식을 사용할 수 있는데, 전부 다 쓸 수 있는 것은 아니고 %e, %f, %g 정도가 가능한 듯. 아래의 예시를 보자.

# %.2f: 소수점 아래 2자리까지 출력, 2부터 3까지 0.5 간격으로
# 정수부분만 출력하고 싶다면 %.0f 사용
seq -f "the number is %.2f" 2 0.5 3
the number is 2.00
the number is 2.50
the number is 3.00

# %e: 지수표현으로 출력, 200부터 300까지 50 간격으로
seq -f "the number is %.2e" 200 50 300
the number is 2.00e+02
the number is 2.50e+02
the number is 3.00e+02

# %g: 부동소수점(%f) 또는 지수표현(%e)중 출력값 길이가 짧은 쪽으로 선택해서 출력
seq -f "the number is %g" 2 0.5 3
the number is 2
the number is 2.5
the number is 3

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 1. 28. 13:36

 

반달가면 이글루에서 백업 - bahndal.egloos.com/498262

 

grep 명령을 이용하면 특정한 문자열을 포함하고 있는 파일들이 뭐가 있는지 찾을 수 있다. 훌륭하군!

일단 기본부터 차근차근 살펴보자. grep 명령의 기본 형식은 아래와 같다.

# [옵션]을 적용하여 [파일]의 내용을 검색, [문자열]을 찾음
grep [옵션] [문자열] [파일]

 

이제 아래의 예시를 보자. my_memo.txt 파일에서 abcd 문자열이 포함되어 있는지 검색하고 파일명과 함께 문자열이 포함된 행을 찾아 출력하는 것이다. -H 옵션을 주면 찾은 문자열뿐만 아니라 해당 파일명을 같이 출력해 준다. 파일명과 문자열은 콜론(:)으로 구분된다.

 

grep -H abcd my_memo.txt

my_memo.txt:abcdef

 

문자열은 필요 없고 파일명만 확인하고 싶다면 아래와 같이 -l 옵션을 추가하자.

 

grep -Hl abcd my_memo.txt

my_memo.txt

 

자, 이제 특정 디렉토리와 그 하위 디렉토리에 있는 여러개의 파일들 중에 특정한 문자열을 포함한 파일이 있는지 찾고 파일명을 확인해 보자. -r 옵션(recursive)을 이용하고 파일 대신 디렉토리를 지정하면 된다. 아래의 예시는 ~/Documents 디렉토리의 모든 파일을 검색, 내용에 abcd가 포함된 파일 찾아 파일명을 출력하는 경우이다.

 

grep -Hlr abcd ~/Documents

 

만약 특정 파일만 골라서 확인하고 싶다면 --include 옵션을 추가한다. 아래의 예시는 확장자가 txt인 파일만 대상으로 검색하는 경우이다.

 

grep -Hlr --include=*.txt abcd ~/Documents txt

 

파일 중에 v로 시작되는 파일은 제외하고 검색하려면 여기에 --exclude 옵션을 추가.

 

grep -Hlr --include=*.txt --exclude=v* abcd ~/Documents

 

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 1. 14. 17:21

 

반달가면 이글루에서 백업 - bahndal.egloos.com/486688

 

sleep 명령은 초 단위로만 쉴 수 있다고 생각하고 있었는데, 이제 보니 1초 미만으로 정할 수 있구나. (sleep 명령의 man 페이지를 보니 소수점도 사용할 수 있다고 나와있다.)

아래의 예시를 참조하자.

# 0.1초 쉬기
sleep 0.1

# 1시간 30분 30초동안 쉬기
sleep 1h 30m 30s
# 1.5시간 동안 쉬기
sleep 1.5h

 

Posted by 반달가면

댓글을 달아 주세요

bash script (backup)2021. 1. 6. 13:15

 

반달가면 이글루에서 백업 - bahndal.egloos.com/476203

 

무작위로 이름이 정해지고 해당 사용자에게만 접근권한이 있는 임시 파일 또는 임시 디렉토리를 만들고 싶다면 mktemp 명령을 활용하자. 일단 아래의 예시를 보자.

 

mktemp myfile_XXXX.tmp

myfile_iX9v.tmp (파일이 생성된 후, 이름이 출력된다)

 

현재 디렉토리에서 "myfile_"로 시작되고 바로 뒤 4개 글자가 무작위로 정해지면서 확장자가 .tmp인 파일을 만든 후 파일 이름이 화면에 출력되었다. 이름에서 'X'라고 된 부분이 무작위로 바뀌며, 최소한 3개 이상의 'X'를 지정해야 한다.

 

임시 디렉토리를 만들고 싶다면 -d 옵션을 이용.

 

mktemp -d mydir_XXXX

mydir_jKuI (디렉토리가 생성된 후, 이름이 출력된다)

 

그냥 touch 또는 mkdir 명령을 사용해도 될 것 같은데 굳이 mktemp 명령이 필요한 이유는 무엇일까?

 

사실 홈 디렉토리에서 임시 파일을 만든다면 mktemp 명령을 굳이 쓰지 않아도 될 것 같다. 하지만 메모리 영역(RAM)에 연결된 /dev/shm 디렉토리에 임시 파일을 만들고 싶다면 되도록 mktemp 명령을 사용하는 것이 안전하다. /dev/shm 디렉토리의 권한이 777(rwxrwxrws)로 설정되어 있어 모든 사용자가 접근할 수 있기 때문이다.

 

반복적인 읽기/쓰기가 이루어지는 경우에 임시 파일을 일종의 램디스크인 /dev/shm 디렉토리에 만들면 디스크보다 훨씬 빠르다는 장점이 있다. 접근권한의 문제는 mktemp 명령으로 해결하면 된다. mktemp 명령으로 생성된 임시 파일의 권한은 600(rw-------), 임시 디렉토리의 권한은 700(rwx------)이다. 즉, 소유자만 접근 가능.

 

mktemp /dev/shm/myfile_XXXX.tmp

/dev/shm/myfile_BW66.tmp (파일 생성후 파일명 출력)

 

스크립트에서는 아래의 예시를 참고해서 활용해 보자. mktemp 명령의 출력 결과를 변수에 할당해서 사용하면 되겠다.

 

# 임시 디렉토리를 만들어 이름을 tmp_dir 변수에 할당

tmp_dir=`mktemp -d /dev/shm/mydir_XXXX`

# 임시 디렉토리 안에 임시 파일을 만들고 이름을 tmp_file 변수에 할당

tmp_file=`mktemp $tmp_dir/myfile_XXXX.tmp`

echo "temp file created: $tmp_file"

# 이제 임시 파일을 사용하면 된다. 문자열 abcde를 임시 파일에 저장

echo "abcde" > $tmp_file

...

# 임시 파일 삭제

rm $tmp_file

# 임시 디렉토리 삭제

rm -r $tmp_dir

 

 

Posted by 반달가면

댓글을 달아 주세요