Run The Bridge

shell script master -6- 본문

Cloud/Linux

shell script master -6-

anfrhrl5555 2022. 1. 27. 00:36
728x90

0. 배열

 declare -a array1=("water" "blue" "super")  # declare를 통해 배열을 선언한다.
declare -a array2=("melon" "mountain" "stars")  # 배열은 공백문자로 분리된다.

---

for loop를 통해 두 개의 배열을 결합해서 출력한다.

for i in "${!array1[@]}"; do  # 인덱스 번호 0, 1, 2출력
>     printf "%s\t%s\t%s\n" "$i" "${array1[$i]}" "${array2[$i]}"
> done
0       water   melon
1       blue    mountain
2       super   stars

---

그러면 ${!array1[@]에 '!'는 뜻이 뭘까?

# = length를 뽑아준다.

@ = 모든 요소를 출력한다.

echo ${!array1[@]}
0 1 2
echo "${array1[@]}"
water blue super

위 두개의 테스트로 짐작해보면.. '!'는 인덱스 번호를 출력해주는 것을 알 수 있다.

 

그래서 for loop에서 [$i]로 표시해셔 인덱스 번호가 들어가게 스크립트를 작성한 것이다.


1. 배열과 glob 그리고 루프문

배열에서 declare를 쓰는건 약간 번거로운일이다. 

 

배열을 선언할 때, declare를 쓰지않고 배열을 선언하는 방법이 있다.

ARRAY=( "sky:blue" "snow:white" "night:black" "apple:red" )  # 앞 뒤로 공백을 둔다.
for object in "${ARRAY[@]}"; do  # 배열을 참조할 때 인용부호를 꼭 써주어야 한다.
>     KEY=${object%%:*}
>     VALUE=${object#*:}
>     printf "%s's color is %s. \n" "$KEY" "$VALUE"
> done
sky:blue's color is blue.
snow:white's color is white.
night:black's color is black.
apple:red's color is red.

---

ARRAY값은 다음을 담고있다.

echo "${ARRAY[@]}"
sky:blue snow:white night:black apple:red

---

파일에 명령을 담을 때는 glob을 사용해서 담아주어야 오류를 피할 수 있다.

files=$(ls)  # bad
files=($(ls))  # bad
files=(*)  # good, 배열초기화 방법

2. 실습(DRILL)

CSV 같은 쉼표로 구분된 문자열을 처리해 보세요

 

아래와 같은 이름의 파일들을 스크립트을 통해 만들어지도록 작성하세요.

youtube,ai,alphago,arduino,IoT

막 삽질해서 만들긴했다. ㅋㅋㅋ 40분정도 걸렸다

#!/bin/bash

num=99

for i in `eval echo {1..$num}`
do
        VALUES=`cut -d"," -f${i} $1`
        if [[ $VALUES == "" ]]
        then
                break;
        else
                if [[ $? == 1 ]]
                then
                        mkdir $VALUES
                        echo "make ${VALUES}"
                fi
        fi
done

','를 기준으로 값을 나누고, 해당 값을 변수에 넣는게 어려워서 야매로 약간 짜보았다.

 

야매지만 아무리 많은 값이 있어도, 해당 값이 더이상 없으면 break 되게 설정되어 있으며 num 값만 바꾸면 많은 값들도 mkdir로 만들어 낼 수 있다.

 

이제 강사님 답지를 보자.

#!/usr/bin/env bash
# makeTagDirectory.sh tech.txt

IFS=$',' read -r -a array < $1
for element in "${array[@]}"
do
    echo "---" > "$element.md"
    echo "name: $element" >> "$element.md"
    echo "title: '$element'" >> "$element.md"
    echo "---" >> "$element.md"
done

---

디버깅을 해보았다.

bash -x makeTagDirectory.sh tech.txt
+ IFS=,
+ read -r -a array
+ for element in '"${array[@]}"'
+ echo ---
+ echo 'name: youtube'
+ echo 'title: '\''youtube'\'''
+ echo ---
+ for element in '"${array[@]}"'
+ echo ---
+ echo 'name: ai'
+ echo 'title: '\''ai'\'''
+ echo ---
+ for element in '"${array[@]}"'
+ echo ---
+ echo 'name: alphago'
+ echo 'title: '\''alphago'\'''
+ echo ---
+ for element in '"${array[@]}"'
+ echo ---
+ echo 'name: arduino'
+ echo 'title: '\''arduino'\'''
+ echo ---
+ for element in '"${array[@]}"'
+ echo ---
+ echo 'name: IoT'
+ echo 'title: '\''IoT'\'''
+ echo ---

처음에 IFS라는 값에 ','를 넣어두고 분리를 하신 것 같다. 

 

read에 array라는게 있었다...내일 사용해본다..슈방..ㅠㅠ

 

영상을 보다가 끊었는데 후반부에 보니.. read, for loop, 배열, IFS를 쓰라고 나오네.. 이래서 한국말은..ㅋㅋ


3. find 와 -print0

 find . -name "*.mp3" | xargs rm -rf

다음과 같은 mp3 파일들을 찾고, 삭제하는 명령어

./For Whom the Bell Tolls.mp3
./Gone With the Wind.mp3
./The old man and the sea.mp3

근데 실행하니까 삭제가 안된다 ㅋㅋ why?

---

ls로 바꿔보니 공백 + 줄바꿈 때문에 전부 분리되어서 안되었다. 약간 인용부호를 또 쓸 거 같은 느낌이...

 find . -name "*.mp3" | xargs ls
ls: cannot access ./For: No such file or directory
ls: cannot access Whom: No such file or directory
ls: cannot access the: No such file or directory
ls: cannot access Bell: No such file or directory
ls: cannot access Tolls.mp3: No such file or directory
ls: cannot access ./Gone: No such file or directory
ls: cannot access With: No such file or directory
ls: cannot access the: No such file or directory
ls: cannot access Wind.mp3: No such file or directory
ls: cannot access ./The: No such file or directory
ls: cannot access old: No such file or directory
ls: cannot access man: No such file or directory
ls: cannot access and: No such file or directory
ls: cannot access the: No such file or directory
ls: cannot access sea.mp3: No such file or directory

---

hexdump를 떠서 공백문자 0x20, 0x0a를 찾는다.

 find . -iname "*.mp3" | hexdump -C
00000000  2e 2f 46 6f 72 20 57 68  6f 6d 20 74 68 65 20 42  |./For Whom the B|
00000010  65 6c 6c 20 54 6f 6c 6c  73 2e 6d 70 33 0a 2e 2f  |ell Tolls.mp3../|
00000020  47 6f 6e 65 20 57 69 74  68 20 74 68 65 20 57 69  |Gone With the Wi|
00000030  6e 64 2e 6d 70 33 0a 2e  2f 54 68 65 20 6f 6c 64  |nd.mp3../The old|
00000040  20 6d 61 6e 20 61 6e 64  20 74 68 65 20 73 65 61  | man and the sea|
00000050  2e 6d 70 33 0a                                    |.mp3.|
00000055

---

여기서 '-print0'를 사용한다.

find 명령어에 의해 검색된 모든 검색 결과의 마지막에 null 문자를 넣어준다.

---

별차이 없어보이지만.. mp3로 끝나는 문자열 마지막에 0x00이 들어간 것을 볼 수 있다.

 find . -iname "*.mp3" -print0 | hexdump -C
00000000  2e 2f 46 6f 72 20 57 68  6f 6d 20 74 68 65 20 42  |./For Whom the B|
00000010  65 6c 6c 20 54 6f 6c 6c  73 2e 6d 70 33 00 2e 2f  |ell Tolls.mp3../|
00000020  47 6f 6e 65 20 57 69 74  68 20 74 68 65 20 57 69  |Gone With the Wi|
00000030  6e 64 2e 6d 70 33 00 2e  2f 54 68 65 20 6f 6c 64  |nd.mp3../The old|
00000040  20 6d 61 6e 20 61 6e 64  20 74 68 65 20 73 65 61  | man and the sea|
00000050  2e 6d 70 33 00                                    |.mp3.|
00000055

---

여기서 'xargs -0'에서 '-0'옵션은 문자열을 널문자로 분리하려면 필수적으로 써야하는 옵션이다.

find . -iname "*.mp3" -print0 | xargs -0 ls
./For Whom the Bell Tolls.mp3  ./Gone With the Wind.mp3  ./The old man and the sea.mp3

---

그러면 이렇게 사용할 수 있다. 그러면 공백문자 + 줄바꿈 문자 모두 삭제된다.

find . -iname "*.mp3" -print0 | xargs -0 rm -rf

추가로 -iname은 grep -i 에서 사용하였듯이 대소문자 구별 없이 모두 찾는다.


4. 명령어(find)

find ./ -maxdepth 1 -iname '*.sh'  # 현재 경로에서만 한정해서 확장자명 sh를 모두 찾는다.
./helloworld.sh
find ./ -maxdepth 2 -iname '*.sh'  # maxdepth를 2로 하자 더 많이 찾아준다.
./shell_script/VAR.sh
./shell_script/factor.sh
./shell_script/while_DRILL.sh
./shell_script/date_DRILL.sh
./shell_script/seq_DRILL.sh
./helloworld.sh

---

추가로 이 명령 끝에 세미콜론(;)를 사용해주어야 한다.

 find ./ -name "*.bak" -exec ls -l {} \;  # 검색결과가 {}에 담기고 ls -l에 의해 출력된다.
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/Balloon.jpg.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/Candy.jpg.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/glob.gif.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/settings_down.png.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/settings_up.png.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/shadingimage.tiff.bak
-rw-r--r--. 1 root root 0 Jan 26 01:24 ./shell_script/shell_cmd/images/smaller.tiff.bak
-rw-r--r--. 1 root root 6 Jan 23 23:02 ./shell_script/shell_cmd/hello.txt.bak

우리는 여기서 'ls -l'를 'rm -rf'으로 바꿔서 응용된다는 것도 알 수 있다.

---

find ./ -type d  # 디렉토리만 검색

---

 find ~/ -maxdepth 1 -name ".*"  # 히든파일을 찾는방법
/root/.bash_logout
/root/.bash_profile
/root/.cshrc
/root/.tcshrc
/root/.bash_history
/root/.bashrc
/root/.pki
/root/.kube
/root/.docker
/root/.lesshst
/root/.kubectx
/root/.viminfo

---

두 개의 find를 조합하는 방법

'-a': and

 find ./ \( -user user -a -perm 644 \) -print | xargs ls -l
find: ‘user’ is not the name of a known user
total 8
-rw-------. 1 root root 1419 Jan  6 20:29 anaconda-ks.cfg
drwxr-xr-x. 2 root root    6 Jan 20 23:23 dir1
-rwxr-xr-x. 1 root root   17 Jan  6 22:54 helloworld.sh
drwxr-xr-x. 5 root root   47 Jan 19 22:39 newproject
drwxr-xr-x. 5 root root  185 Feb  3 22:46 shell_script
drwxr-xr-x. 2 root root    6 Jan 16 18:10 test

감사합니다.

728x90

'Cloud > Linux' 카테고리의 다른 글

shell script master -8-  (0) 2022.01.27
shell script master -7-  (0) 2022.01.27
shell script master -5-  (0) 2022.01.21
shell script master -4-  (0) 2022.01.13
i-node 실습  (0) 2022.01.12
Comments