절대 경로와 상대 경로
55분 안팎
학습 목표
공백이 있는 실습 경로에서 파일 생성·복사·검색 결과를 확인합니다.
개념
파일을 다루기 전에 기준점을 정합니다
같은 복사 명령이 어떤 날은 성공하고 어떤 날은 다른 파일을 만드는 이유는 현재 디렉터리가 달라졌기 때문일 수 있습니다. 운영 자료는 경로가 곧 대상의 일부입니다. 이번 레슨은 lab-root 아래 data, config, evidence를 만들고 공백이 들어 있는 입력 폴더에서 설정을 복사합니다. 파일 내용을 확인한 기록까지 남겨 다음 레슨의 입출력 연습에 사용할 수 있게 합니다.
절대 경로는 루트 디렉터리 /에서 시작합니다. 상대 경로는 현재 작업 디렉터리에서 해석합니다. data/app.txt는 지금 위치 아래의 data이지만 /data/app.txt는 루트 아래의 data입니다. 둘이 같은 파일이라는 보장은 없습니다. pwd로 현재 위치를 확인하고 명령의 경로가 어느 기준을 쓰는지 말로 설명한 뒤 실행합니다. 홈 아래 실습 경로를 쓰면 다른 프로젝트 파일과 대상이 섞이는 일을 줄일 수 있습니다.
점 하나는 현재 디렉터리, 점 두 개는 부모 디렉터리입니다. cd ..를 실행하면 이후 상대 경로의 기준점도 바뀝니다. 셸에서 cd가 성공했는지 확인하지 않고 다음 복사를 진행하면 엉뚱한 위치에 결과를 남길 수 있습니다. 스크립트에서는 cd 실패를 중단 조건으로 다루고, 내려받은 실습의 검사기는 자기 파일이 있는 폴더로 이동한 다음 검사를 시작합니다.
경로 하나가 인자 하나가 되게 합니다
셸은 명령 문자열을 해석하고 명령에 인자 목록을 넘깁니다. 폴더 이름 incoming files를 따옴표 없이 쓰면 공백이 구분자로 처리될 수 있습니다. mkdir incoming files는 두 폴더를 만들 수 있지만 mkdir "incoming files"는 하나의 이름을 전달합니다. 경로 변수도 같은 이유로 "$root"처럼 큰따옴표로 감쌉니다. 변수에 공백이 없었던 날 성공한 코드만으로 안전성을 판단하지 않습니다.
큰따옴표는 변수 치환을 허용하면서 치환된 경로가 여러 단어로 나뉘는 것을 막습니다. 작은따옴표로 감싼 문자열 안의 $root는 변수 값이 아니라 글자 그대로입니다. 따라서 고정된 파일 내용은 작은따옴표로, 값을 사용하는 경로는 큰따옴표로 적는 구분이 도움이 됩니다. 따옴표를 쓴다고 경로가 존재하게 되는 것은 아니므로 존재 여부와 인자 분리 문제를 나눠 봅니다.
이 실습의 루트는 task.sh의 첫 인자로 전달합니다. ${1:?작업 루트 인자가 필요합니다}는 인자가 없거나 비었을 때 안내와 함께 중단합니다. mkdir -p는 필요한 중간 디렉터리를 만들고 이미 있는 디렉터리에 대해서도 진행합니다. 같은 이름이 일반 파일인 경우에는 실패할 수 있습니다. 실패를 무시하고 복사를 진행하기보다 어떤 경로 구성요소가 파일인지 확인합니다.
생성·복사·확인을 순서대로 합니다
먼저 data/incoming files/source.txt에 service=lab-web와 state=ready를 두 줄로 만듭니다. printf는 정해진 형식으로 줄바꿈을 생성하므로 예제의 파일 내용을 일정하게 만들 수 있습니다. >는 파일을 새로 만들거나 기존 내용을 덮어씁니다. 이 단계는 매번 같은 상태로 돌아가는 예제이므로 덮어쓰기를 선택합니다. 작업 기록을 누적해야 하는 상황의 방식과는 목적이 다릅니다.
cp는 원본의 내용을 목적 파일로 복사합니다. 목적 경로가 디렉터리이면 원본 이름이 그 아래로 들어가지만 이번 예제에서는 목적 파일 config/app.conf를 명시합니다. 복사가 종료 코드 0으로 끝났다는 사실과 파일 내용이 기대와 같다는 사실을 함께 확인합니다. cmp는 두 파일을 비교하여 같으면 별도 내용을 출력하지 않고 성공합니다. 조용한 명령의 성공도 종료 코드로 판단할 수 있습니다.
grep -n -F는 고정 문자열 state=ready가 있는 행을 행 번호와 함께 보여 줍니다. 여기서는 설정을 수정하지 않고 내용을 검색합니다. 행 번호를 붙이면 복사된 설정의 어느 줄이 확인 대상인지 증거가 됩니다. 이 두 줄 파일에서는 2:state=ready가 기록됩니다. 폴더를 올바르게 만들었어도 복사 대상이 달랐다면 이 검색 결과가 기대와 다를 수 있습니다.
명령 이름과 오류 대상을 함께 읽습니다
cp의 No such file or directory는 원본이 없을 수도 있고 목적의 부모 디렉터리가 없을 수도 있습니다. 메시지에 나온 경로를 보고 pwd, ls -ld와 파일 이름을 확인합니다. 공백이 들어간 경로가 둘로 잘린 경우에도 같은 문구가 나올 수 있으므로 인용을 검토합니다. 권한을 올리기 전에 지금 위치와 인자를 확인하면 관리자 작업 없이 해결되는 오류를 찾을 수 있습니다.
Permission denied는 읽기 또는 쓰기 권한 부족일 수 있습니다. 원본 읽기, 목적 디렉터리에 새 파일 만들기, 기존 목적 파일 덮어쓰기 중 어느 동작이 실패했는지 구분합니다. 이번 레슨은 홈 아래 새 자료만 쓰며 시스템 디렉터리를 바꾸지 않습니다. chmod를 넓게 적용하는 방법 대신 대상과 소유자를 기록합니다. 상세한 파일 권한 설계는 다음 모듈의 주제입니다.
검색 결과가 비어 있으면 파일 없음과 내용 불일치를 구분해야 합니다. 파일이 있고 문자열이 없으면 grep은 1을 반환하며, 읽을 수 없는 파일 등 오류에서는 다른 실패 코드를 반환합니다. 화면에 보이는 빈 줄만으로 복사 실패라고 결론 내리지 않습니다. cat으로 작은 실습 파일의 내용을 보고 cmp와 grep의 종료 상태를 나눠 확인하면 경로·내용·검색 조건을 각각 좁힐 수 있습니다.
검사 범위를 넓혀 재현합니다
실습 검사기는 임시 폴더 아래 공백 이름, 한글 이름, 일반 이름의 세 루트에서 task.sh를 실행합니다. 각 루트에 디렉터리 세 개가 있고 원본과 설정이 같으며 검색 기록이 맞는지 확인합니다. 원래 다운로드 폴더만 검사하면 변수 인용 실수가 숨을 수 있습니다. 서로 다른 이름을 통해 구현이 특정 고정 경로에 우연히 기대지 않았는지 확인합니다.
두 번 실행하는 검사도 있습니다. 같은 내용으로 다시 준비했는데 설정 줄이 네 줄로 늘었다면 >>를 사용해 불필요하게 추가했을 수 있습니다. 디렉터리 존재만 보고 통과시키지 않고 파일 줄 수와 내용을 비교합니다. 재실행 가능성은 운영 자동화에서 중요하지만 이번 실습은 제한된 파일 구성만 다룹니다. 전체 시스템에 대해 멱등성이 보장된다고 확대해 설명하지 않습니다.
파일 이름의 대소문자는 환경에 따라 다르게 처리될 수 있습니다. Linux 실습에서는 source.txt와 Source.txt를 서로 다른 이름으로 취급하는 경우가 일반적이므로 계획한 이름을 일관되게 씁니다. 맥에서 성공한 오타가 VM에서 실패하면 이름과 경로를 먼저 대조합니다. 임의의 사용자 파일을 대상으로 실험하기보다 실습에서 만든 작은 텍스트를 사용하면 결과를 비교하기 쉽습니다.
경로 기록을 인계 자료로 바꿉니다
인계할 때는 파일 이름만 나열하지 않고 루트 아래의 상대 위치와 생성 순서를 적습니다. data는 원본, config는 실행 설정, evidence는 확인 결과라는 역할을 유지합니다. 다음 담당자는 그 기록을 기준으로 복사와 검색을 반복할 수 있습니다. 심볼릭 링크와 경로 정규화는 더 읽기의 realpath 장에서 확장합니다. 이 레슨의 예제는 링크를 만들지 않아 pwd와 명시된 파일 경로의 관계부터 확인합니다.
따라하기
공백 경로 생성
새 임시 작업 폴더에서 실행합니다. 이후 세 단계는 같은 폴더에서 이어서 실행합니다. 아래 파일 생성 단계는 이미 있던 동명 실습 파일을 덮어씁니다.
mkdir -p "lab root/data/incoming files" "lab root/config" "lab root/evidence"
printf "service=lab-web
state=ready
" > "lab root/data/incoming files/source.txt"
cat "lab root/data/incoming files/source.txt"실행 결과
service=lab-web state=ready
복사 내용 비교
앞 단계와 같은 경로를 만듭니다. 재실행할 수 있도록 입력 준비도 명령에 포함했습니다. cmp가 같음을 확인하면 확인 메시지를 표시합니다.
mkdir -p "lab root/data/incoming files" "lab root/config"
printf "service=lab-web
state=ready
" > "lab root/data/incoming files/source.txt"
cp "lab root/data/incoming files/source.txt" "lab root/config/app.conf"
cmp "lab root/data/incoming files/source.txt" "lab root/config/app.conf" && printf "copy=equal
"실행 결과
copy=equal
고정 문자열 검색
준비한 두 줄 설정에서 일치 행을 기록합니다. 검색은 파일 내용을 바꾸지 않습니다.
mkdir -p "lab root/config" "lab root/evidence"
printf "service=lab-web
state=ready
" > "lab root/config/app.conf"
grep -n -F "state=ready" "lab root/config/app.conf" > "lab root/evidence/search.txt"
cat "lab root/evidence/search.txt"실행 결과
2:state=ready
확인 문제
실습
task.sh를 구현하여 인자로 받은 루트에 원본·설정·검색 기록을 만듭니다. 공백·한글 루트와 재실행에도 내용이 같아야 합니다.
실행 명령
bash check.sh
기대 결과
PASS paths: 3 roots, repeat run
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 점검 스크립트가 실패를 알리는 방식을 설명합니다.