2  파일과 폴더 넘나들기

파일과 디렉토리 관리를 담당하고 있는 운영체제 부분을 파일 시스템(file system)이라고 한다. 파일 시스템은 데이터를 정보를 담고 있는 파일과 파일 혹은 다른 디렉토리를 담고 있는 디렉토리(혹은 “폴더”)로 조직화한다.

파일과 디렉토리를 만들고, 검사하고, 이름 바꾸고, 삭제하는데 명령어 몇개가 자주 사용된다. 명령어를 살펴보기 위해, 쉘 윈도우를 연다:

먼저, pwd 명령어를 사용해서 위치를 찾아낸다. pwd는 “print working directory”를 의미한다. 디렉토리는 장소(place) 같다 - 쉘을 사용할 때마다 정확하게 한 장소에 위치하게 되는데, 이를 현재 작업 디렉토리(current working directory)라고 부른다. 명령어 대부분은 현재 작업 디렉토리에 파일을 읽고 쓰는 작업을 “이곳(here)”에 수행한다. 그래서 명령어를 실행하기 전에 현재 위치가 어디인지 파악하는 것이 중요하다. pwd 명령어를 실행하면 현재 위치를 다음과 같이 보여주게 된다:

$ pwd
/Users/nelle

맥OS의 사례로서, 컴퓨터의 응답은 /Users/nelle으로 넬(Nelle)의 홈 디렉토리(home directory)를 뜻한다:

홈 디렉토리(Home Directory) 변종

홈 디렉토리 경로는 운영체제마다 다르게 보인다. 리눅스에서 /home/nelle 처럼 보이고, 윈도우에서는 C:\Documents and Settings\nelle, C:\Users\nelle와 유사하게 보인다. (윈도우 버젼마다 다소 차이가 있을 수 있음에 주목한다.) 다음 예제부터, 맥OS 출력결과를 기본설정으로 사용하고, 리눅스와 윈도우 출력결과에 다소 차이가 날 수 있지만, 전반적으로 유사하다.

“홈 디렉토리(home directory)”를 이해하기 위해서, 파일 시스템이 전체적으로 어떻게 구성되었는지 살펴보자. 최상단에 다른 모든 것을 담고 있는 루트 디렉토리(root directory)가 있다. 슬래쉬 / 문자로 나타내고, /users/nelle에서 맨 앞에 슬래쉬이기도 하다.

2.1 파일 시스템 사례

넬(Nelle) 과학자 컴퓨터 파일시스템을 사례로 살펴보자. 시연을 통해서 유사한 방식으로 (하지만 정확하게 동일하지는 않지만) 본인 컴퓨터 파일시스템을 탐색하는 명령어를 학습하게 된다. 넬 과학자 컴퓨터의 파일 시스템은 그림 fig-filesystem같이 도식적으로 표현할 수 있다:

그림 2.1: 파일 시스템

최상단에 다른 모든 것을 담고 있는 루트 디렉토리(root directory)가 있다. 슬래쉬 / 문자로 나타내고, /users/nelle에서 맨 앞에 슬래쉬이기도 하다.

홈 디렉토리 안쪽에 몇가지 다른 디렉토리가 있다: bin (몇몇 내장 프로그램이 저장된 디렉토리), data (여러가지 데이터 파일이 저장된 디렉토리), Users (사용자의 개인 디렉토리가 저장된 디렉토리), tmp (장기간 저장될 필요가 없는 임시 파일을 위한 디렉토리), 등등.

현재 작업 디렉토리 /Users/nelle/Users 내부에 저장되어 있다는 것을 알고 있는데, 이유는 /Users가 이름 처음 부분이기 때문에 알 수 있다. 마찬가지로 /Users는 루트 디렉토리 내부에 저장되어 있다는 것을 알 수 있는데, 이름이 /으로 시작되기 때문이다.

슬래쉬(Slashes)

슬래쉬 / 문자는 두가지 의미가 있는 것에 주목한다. 파일 혹은 디렉토리 이름 앞에 나타날 때, 루트 디렉토리를 지칭하게 되고, 이름 가운데 나타날 때, 단순히 구분자 역할을 수행한다.

그림 fig-home-directory에서 Nelle 과학자 컴퓨터 계정과, 랩실 동료 미이라(Mummy)와 늑대인간(Wolfman) 디렉토리를 볼 수 있다.

그림 2.2: 홈 디렉토리

미이라(Mummy), imhotep 파일은 /Users/imhotep 디렉토리에 저장되어 있고, 늑대인간(Wolfman), larry 파일은 /Users/larry 디렉토리에 저장되어 있고, /Users/nelle 디렉토리에 nelle의 정보가 저장되어 있는데, 이것이 왜 /Users/nelle이 홈 디렉토리인 이유다. 일반적으로 명령 프롬프트를 열게 되면, 처음 시작하는 곳이 본인 계정 홈 디렉토리가 된다.

본인 파일시스템에 담긴 내용물을 파악하는데 사용하는 명령어를 학습해 보자. (Nelle의 홈 디렉토리에 무엇이 있는지 ls 명령어를 실행해서 살펴보자.) ls는 “목록화(listing)”를 나타낸다:

$ ls
Applications Documents    Library      Music        Public
Desktop      Downloads    Movies       Pictures

(다시 한번, 본인 컴퓨터 운영체제와 파일시스템을 취향에 따라 바꿨는지에 따라 출력결과는 다소 다를 수 있다.)

ls는 알파벳 순서로 깔끔하게 열로 정렬하여 현재 디렉토리에 있는 파일과 디렉토리 이름을 출력한다.

플래그(flag, 스위치(switch) 혹은 옵션(option)으로도 불린다) -F를 추가하여 출력을 좀 더 이해하기 좋게 출력결과를 생성할 수도 있다. 파일 및 디렉토리 이름에 마커를 추가하여 출력이 무엇인지 표시하여 분류하도록 ls 명령어에 -F 옵션을 추가했다.

  • 끝에 붙은 /은 디렉토리라는 것을 지칭한다.
  • @은 링크를 표식한다.
  • *은 실행파일을 나타낸다.

설정에 따라 달라지도록 파일이냐 디렉토리냐에 따라 다른 색상을 입힐 수도 있다. 앞선 학습에서 ls -F 명령어를 사용한 것을 상기한다.

$ ls -F
Applications/ Documents/    Library/      Music/        Public/
Desktop/      Downloads/    Movies/       Pictures/

여기서 홈 디렉토리에 하위-디렉토리(sub-directory)만 포함된 것만 확인된다. 출력에서 분류 기호(/)가 없는 이름은 현재 작업 디렉토리에 속한 파일(file)임을 나타낸다.

터미널 지우기

화면이 너무 지져분해지면, clear 명령을 사용하여 터미널을 깔끔하게 지울 수 있다. 이전 명령은 여전히 ↑ 및 ↓를 사용하여 한 줄씩 이동하거나 터미널에서 스크롤 기능을 사용해서 계속 사용할 수 있다.

2.2 도움말 얻기

ls 명령어에 딸린 플래그가 많다. 일반적으로 명령어와 수반되는 플래그 사용법을 파악하는 방식이 두개 있다.:

  1. --help 플래그를 명령어에 다음과 같이 전달하는 방법:
$ ls --help
  1. man 명령어(리눅스와 맥OS에서 사용 가능)로 다음과 같이 매뉴얼을 읽는 방법:
$ man ls 

본인 컴퓨터 환경에 따라 상기 방법 중 하나만 동작(man 혹은 --help)할 수도 있다. 아래에서 두가지 방법 모두 살펴보자.

내장 명령어에 대한 도움말

명령어 일부는 파일 시스템에 별도 프로그램으로 존재하지 않고 배쉬 쉘에 내장되어 있다. 한 가지 예로, cd(디렉토리 변경) 명령을 들 수 있다. No manual entry for cd 같은 메시지가 화면에 뿌려지면, help cd를 사용한다. help 명령어를 통해 배쉬 기본 제공기능(Bash built-ins)에 대한 사용 정보를 얻을 수 있다.

2.2.1 --help 플래그

배쉬(Bash, Bourne Again Shell) 내부에서 동작하도록 작성된 대부분의 배쉬 명령어와 프로그램은 --help 플래그를 지원한다. 이를 통해 명령어 혹은 프로그램을 사용하는 방식에 대해 더 많은 정보를 확인할 수 있다.

$ ls --help

Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.

Mandatory arguments to long options are mandatory for short options too.
  -a, --all                  do not ignore entries starting with .
  -A, --almost-all           do not list implied . and ..
      --author               with -l, print the author of each file
  -b, --escape               print C-style escapes for nongraphic characters
      --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                               '--block-size=M' prints sizes in units of
                               1,048,576 bytes; see SIZE format below
  -B, --ignore-backups       do not list implied entries ending with ~
  -c                         with -lt: sort by, and show, ctime (time of last
                               modification of file status information);
                               with -l: show ctime and sort by name;
                               otherwise: sort by ctime, newest first

... 중략

  -X                         sort alphabetically by entry extension
  -Z, --context              print any security context of each file
  -1                         list one file per line.  Avoid '\n' with -q or -b
      --help     display this help and exit
      --version  output version information and exit

The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).

Using color to distinguish file types is disabled both by default and
with --color=never.  With --color=auto, ls emits color codes only when
standard output is connected to a terminal.  The LS_COLORS environment
variable can change the settings.  Use the dircolors command to set it.

Exit status:
 0  if OK,
 1  if minor problems (e.g., cannot access subdirectory),
 2  if serious trouble (e.g., cannot access command-line argument).

GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
Full documentation at: <http://www.gnu.org/software/coreutils/ls>
or available locally via: info '(coreutils) ls invocation'
지원되지 않는 명령-라인 선택옵션

지원되지 않는 선택옵션(플래그)를 사용하게 되면, ls를 비롯한 다른 프로그램은 다음과 같은 오류 메시지를 일반적으로 출력시킨다:

$ ls -j
ls: invalid option -- 'j'
Try 'ls --help' for more information.

2.2.2 man 명령어

ls에 대해 배울 수 있는 다른 방식은 다음 명령어를 타이핑하는 것이다.

$ man ls

상기 명령어를 실행하게 되면 ls 명령어와 선택 옵션에 대해 기술된 페이지로 탈바꿈하게 된다. 만약 운이 좋은 경우 상용법에 대한 예제도 포함되어 있다.

man 페이지를 살펴보는 방법은 행단위로 이동하는데 ↑, ↓을 사용하거나 전체 페이지 단 위로 건너뛰거나 아래 페이지로 이동할 경우 B, 을 사용한다.

man 페이지에서 단어나 문자를 찾는 경우 / 다음에 검색할 문자 혹은 단어를 타이핑하면 된다. 간혹 검색 결과에서 여러 개가 검색되는 경우가 있다. 이 경우 N(앞으로 이동)과 Shift+N(뒤로 이동)을 사용하여 검색결과 앞뒤로 이동한다.

man 페이지에서 빠져 나가고자 종료(quit)하고자 한다면 Q을 누른다.

주의

웹상의 매뉴얼 페이지

물론 명령어에 대한 도움말에 접근하는 세번째 방식이 있다: 웹브라우저를 통해서 인터넷을 검색하는 것이다. 인터넷 검색을 이용할 때, 검색쿼리에 unix man page 문구를 포함할 경우 연관된 정보를 찾는데 도움이 될 수 있다.

GNU도 GNU 핵심 유틸리티(core GNU utilities)이 포함된 매뉴얼을 제공하고 있는데, 본서에 소개된 명령어가 다수 망라되어 있다.

예제 2.1 (더많은 ls 플래그 탐색) -l, -h 플래그를 붙여 ls 명령어를 수행하게 되면 출력결과는 어떻게 나올까?

출력결과 일부는 이번 학습에서 다루지 않는 속성(property)에 대한 것으로 파일 권한과 파일 소유에 대한 것을 출력하고 있다. 그럼에도 불구하고 나머지 출력결과는 도움이 된다.

힌트

ls와 사용되는 -l 플래그는 long을 축약한 것으로 파일/디렉토리 명칭 뿐만 아니라 파일 크기, 최종 변경 시간 같은 부가정보가 출력된다. -h 플래그는 “human readable” 사람이 읽기 편한 형태로 파일크기를 지정한다. 예를 들어, 5369 대신에 5.3K이 화면에 출력된다.

예제 2.2 (재귀적으로 시간순으로 목록 출력)  

  1. 기본디폴트 설정으로 ls는 디렉토리 내용을 알파벳 순으로 나열한다. ls -t 명령은 알파벳순이 아닌 마지막으로 변경한 시간순으로 나열한다. ls -r 명령은 디렉토리 내용을 역순으로 나열한다. t-r 옵션을 결합하면 어떤 파일이 가장 마지막에 표시될까요? 힌트: 마지막으로 변경된 날짜를 보려면 -l 옵션을 사용하면 도움이 됩니다.

  2. ls -R 명령어는 디렉토리에 담긴 내용을 재귀적으로 화면에 출력한다. 즉, 각 단계별로 하위 디렉토리, 하위-하위 디렉토리 내용을 확면에 출력한다. ls -t 명령어는 마지막 변경된 시점순으로 가장 최근에 변경된 파일 혹은 디렉토리를 화면에 정렬해서 출력한다. ls -R -t 명령어는 어떤 순서로 화면에 출력할까?

힌트: ls -l 명령어를 사용해서 시간도장(timestamp)을 볼 수 있도록 전체 목록을 화면에 출력한다.

힌트
  1. -rt를 사용할 때 가장 최근에 변경된 파일이 가장 마지막에 나열된다. 이 기능은 가장 최근에 수정한 내용을 찾거나 새 출력 파일이 작성되었는지 확인하는 데 매우 유용하다.

  2. 각 디렉토리의 파일/디렉토리가 가장 마지막 시간 변경순으로 정렬되어 출력된다.

2.3 다른 디렉토리 탐색

ls 명령어를 사용해서 다른 디렉토리에 들어 있는 파일과 디렉토리를 살펴볼 수 있다. ls -F Desktop 명령어를 실행해서 바탕화면 Desktop 디렉토리에 담긴 것을 살펴보자. 즉, ls 명령어는 -F 플래그, 그리고 인자(argument) Desktop으로 구성된다. Desktop 인자는 ls로 하여금 현재 작업 디렉토리가 아닌 바탕화면 디렉토리 내용을 출력하도록 지정하는 역할을 수행한다:

$ ls -F Desktop
shell-lesson-data/

현재 작업 디렉토리에 Desktop이라는 디렉토리가 존재하지 않으면 이 명령은 오류를 반환한다. 일반적으로 Desktop 디렉토리는 홈 디렉토리에 존재하며, 이 디렉토리가 현재 배쉬 쉘 작업 디렉토리라고 가정한다.

웹사이트에서 다운로드 받아 압축을 풀게 되면 바탕화면 Desktop 디렉토리 아래 shell-lesson-data 하위 디렉토리가 있다. 작업한 출력결과는 shell-lesson-data 디렉토리에 포함된 모든 파일과 하위디렉토리가 출력되어야 한다. (대부분의 시스템에서 쉘 Desktop 디렉토리 콘텐츠는 그래픽 사용자 인터페이스 아이콘으로 표시된다. 본인에게도 해당되는지 확인한다.)

지금 확인했듯이, 배쉬 쉘은 파일을 계층적 파일 시스템으로 구성한다는 아이디어에 강력히 의존하고 있다. 이런 방식으로 계층적으로 파일과 디렉토리를 구조화하게 되면 본인 작업을 추적하는데 도움이 된다: 책상위에 출력한 논문 수백개를 쌓아놓는 것이 가능하듯이, 홈 디렉토리에 파일 수백개를 저장하는 것도 가능하다. 하지만, 이런 접근법은 자멸하는 전략이나 마찬가지다. 하지만, 의미있는 명칭을 갖는 하위 디렉토리로 구조화하고 파일을 분류하여 정리해두면 나중에 훨씬 더 쉽게 찾을 수 있다.

shell-lesson-data 디렉토리가 바탕화면(Desktop)에 위치하는 것을 확인했으니, 다음 두가지를 수행할 수 있다.

먼저, shell-lesson-data 디렉토리에 담긴 것을 살펴보자. 디렉토리 이름에 ls를 전달해 서 앞서 확인된 동일한 전략을 사용하자:

$ ls -F Desktop/shell-lesson-data
creatures/          molecules/          notes.txt           solar.pdf
data/               north-pacific-gyre/ pizza.cfg           writing/

둘째로, 다른 디렉토리로 위치를 실제로 바꿀 수 있다. 이렇게 하면 더이상 홈 디렉토리에 있지는 않아도 된다.

작업 디렉토리를 변경하기 위해서 cd 다음에 디렉토리 이름을 사용한다. cd는 “change directory”의 두문어다. 하지만 약간 오해의 소지가 있다: 명령어 자체가 디렉토리를 변경하지는 않고, 단지 사용자가 어느 디렉토리에 있는지에 대한 쉘 설정만 바꾼다. cd 명령은 그래픽 인터페이스에서 폴더를 두 번 클릭하여 해당 폴더로 이동하는 것과 유사하다.

앞서 확인한 exercise-data 디렉토리로 이동해 보자. 다음 명령어를 쭉 이어서 실행하게 되면 목적지에 도달할 수 있다:

$ cd Desktop
$ cd shell-lesson-data
$ cd exercise-data

상기 명령어는 홈 디렉토리에 바탕화면(Desktop) 디렉토리로 이동하고 나서, shell-lesson-data 디렉토리로 이동하고 나서, exercise-data 디렉토리에 이동하게 된다. cd 명령어는 아무것도 출력하지는 않지만, pwd 명령어를 실행하게 되면 /Users/nelle/Desktop/shell-lesson-data/exercise-data 위치한 것을 확인하게 된다. 인자 없이 ls 명령어를 실행하게 되면, /Users/nelle/Desktop/shell-lesson-data/data 디렉토리 파일과 디렉토리를 출력하게 되는데 이유는 지금 있는 위치이기 때문이다:

$ pwd
/Users/nelle/Desktop/shell-lesson-data/exercise-data
$ ls -F
animal-counts/  creatures/  numbers.txt  alkanes/  writing/

이제 디렉토리 계통 구조를 타고 아래로 내려가는 방법을 익혔다. 하지만 어떻게 하면 위로 올라갈 수 있을까? 다음 명령어를 시도해보자:

$ cd shell-lesson-data
-bash: cd: shell-lesson-data: No such file or directory

하지만, 오류 발생! 이유가 뭘까?

지금까지 방법으로 cd 명령어는 현재 디렉토리 내부에 하위 디렉토리만 볼 수 있다. 현재 디렉토리에서 상위 디렉토리를 볼 수 있는 다른 방법이 있다. 가장 단순한 것부터 시작해보자.

쉘에서 한단계 위 디렉토리로 이동할 수 있는 단축키가 존재하는데 다음과 같이 생겼다:

$ cd ..

..은 특별한 디렉토리명인데 “현재 디렉토리를 포함하는 디렉토리”, 좀더 간결하게 표현하면 현재 디렉토리의 부모를 의미한다. 물론, cd .. 명령어를 실행하고 나서 pwd을 실행하게 되면 /Users/nelle/Desktop/shell-lesson-data로 되돌아 간다:

$ pwd
/Users/nelle/Desktop/shell-lesson-data

단순히 ls 명령어를 실행하게 되면 특수 디렉토리 ..이 화면에 출력되지는 않는다. .. 디렉토리를 출력하려면 ls 명령어와 -a 플래그를 사용한다:

$ ls -F -a
./   .bash_profile  data/       north-pacific-gyre/  pizza.cfg  thesis/
../  creatures/     molecules/  notes.txt            solar.pdf  writing/

-a는 “show all”의 축약으로 모두 보여주기를 의미한다. ls로 하여금 파일과 ..와 같은 .로 시작하는 디렉토리명도 화면에 출력한다. /Users/nelle 디렉토리에 위치한다면, /Users 디렉토리를 지칭하는데, .도 또 다른 특별한 디렉토리로, “현재 작업 디렉토리 (current working directory)”를 의미한다. 중복되어 불필요해 보일 수 있지만, 곧 .에 대한 사용법을 학습할 것이다.

대부분의 명령라인 도구에서 플래그 다수를 조합해서 플래그 사이 공백없이 단일 -로 사용함에 주목한다: ls -F -als -Fa와 동일하다.

다른 숨은 파일들

숨은 .., . 디렉토리에 더해서, .bash_profile 파일도 봤을 것이다. .bash_profile 파일에는 쉘 환경설정 정보가 담겨져 있다. .으로 시작하는 다른 파일과 디렉토리를 봤을 수도 있다. 이런 파일은 본인 컴퓨터의 다른 프로그램에서 환경설정을 하기 위해서 사용되는 파일과 디렉토리라고 보면 된다. . 접두어를 사용해서 ls 명령어를 사용할 때 이러한 환경설정 파일들이 터미널을 난잡하게 만드는 것을 방지하는 기능을 수행한다.

직교(Orthogonality)

특수 이름 ...ls에만 속하는 것이 아니고, 모든 프로그램에서 같은 방식으로 해석된다. 예를 들어, /Users/nelle/data 디렉토리에 있을 때, ls .. 명령어는 /Users/nelle의 목록을 보여줄 것이다. 어떻게 조합되든 상관없이 동일한 의미를 가지게 될 때, 프로그래머는 이를 직교(orthogonal)한다고 부른다. 직교 시스템은 사람들이 훨씬 배우기 쉬운데, 이유는 기억하고 추적할 특수 사례와 예외가 더 적기 때문이다.

2.4 상대/절대 경로

컴퓨터에 파일시스템을 돌아다니는데 기본 명령어는 pwd, ls, cd을 들 수 있다. 지금까지 사용했던 했던 방식을 벗어난 사례를 살펴보자. 프롬프트에서 cd 명령어를 디렉토리를 특정하지 않고 실행시키면 어떻게 될까?

$ cd

상기 명령어 실행 결과를 어떻게 확인할 수 있을까? pwd 명령어가 정답을 제시한다!

$ pwd
/Users/nelle

어떤 플래그도 없는 cd 명령어는 홈디렉토리로 이동시킨다. 파일시스템에서 방향을 잃었을 경우 큰 도움이 된다.

data 디렉토리로 되돌아가자. 앞서 명령어 세개를 동원했지만 한방에 해당 디렉토리를 명세해서 바로 이동할 수 있다.

$ cd Desktop/shell-lesson-data/data

pwdls -F 명령어를 실행해서 올바른 자리로 돌아왔는지 확인하자. data 디렉토리에서 한단계 위로 올라가려고 하면 cd .. 명령어를 사용했다. 현재 디렉토리 위치에 관계없이 특정 디렉토리로 이동할 수 있는 다른 방식도 있다.

지금까지 디렉토리명을 명세할 때 상대경로(relative paths)를 사용했다. ls 혹은 cd와 같은 명령어와 상대 경로를 사용할 때는 시스템이 파일시스템의 루트 위치(/)에서 차근차근 찾기보다 해당 위치를 현재 위치를 찾아 명령을 실행시킨다.

하지만, / 슬래쉬로 표현되는 루트 디렉토리에서 전체 경로를 추가한 절대경로(absolute path)로 명세하는 것도 가능하다. / 슬래쉬는 컴퓨터가 루트 디렉토리에서 경로를 탐색하도록 지시한다. 따라서, 명령어를 실행할 때 현재 디렉토리 위치에 관계없이 정확한 특정 디렉토리를 항상 명세하게 된다.

절대경로를 사용하면 파일 시스템에 어느 위치에서든 있던 관계없이 data-shell 디렉토리로 이동할 수 있다. 절대경로를 찾기 쉬운 방법은 pwd 명령어를 사용해서 필요한 디렉토리 정보를 추출하고 이를 활용해서 data-shell 디렉토리로 이동한다.

$ pwd
/Users/nelle/Desktop/shell-lesson-data/data
$ cd /Users/nelle/Desktop/shell-lesson-data

pwdls -F 명령어를 실행하게 되면 원하던 디렉토리로 제대로 이동되었는지 확인이 가능하다.

예제 2.3 (절대 경로 vs. 상대 경로) 동일 작업을 수행하는 수많은 방법을 연습문제를 통해 확인해보자. \(\text{/home/amanda/data/}\) 디렉토리에서 시작할 때, Amanda가 홈디렉토리인 \(\text{/home/amanda}\)로 돌아가도록 사용할 수 있는 명령어를 아래에서 선택하시요.

  1. cd .
  2. cd /
  3. cd /home/amanda
  4. cd ../..
  5. cd ~
  6. cd home
  7. cd ~/data/..
  8. cd
  9. cd ..
해답과 설명
  1. No: .은 현재 디렉토리를 나타냄.
  2. No: /는 루트 디렉토리를 나타냄.
  3. No: Amanda 홈 디렉토리른 /Users/amanda임.
  4. No: ../..은 두 단계 거슬러 올라간다. 즉, /Users에 도달함.
  5. Yes: ~은 사용자 홈 디렉토리를 나타내고, 이 경우 /Users/amanda이 됨.
  6. No: 현재 디렉토리 내부에 home 디렉토리가 존재하는 경우 home 디렉토리로 이동하게 됨.
  7. Yes: 불필요하게 복잡하지만, 정답이 맞음.
  8. Yes: 사용자 홈 디렉토리로 이동할 수 있는 단축키를 사용함.
  9. Yes: 한 단계 위로 이동.
단축(Shortcuts) 두개 더

쉘을 ~ (틸드) 문자를 경로의 시작으로 해석해서 “현재 사용자 홈 디렉토리”를 의미하게 된다. 예를 들어, Nelle의 홈 디렉토리가 /Users/nelle이라면, ~/data/Users/nelle/data와 동치가 된다. 경로명에 첫 문자로 있을 때만 이것이 동작한다: here/there/~/elsewherehere/there/Users/nelle/elsewhere이 되는 것은 아니다. 따라서, cd ~을 홈 디렉토리로 변경하는데 사용한다.

또 다른 단축은 대쉬(-) 문자다. cd- 문자를 지금 있는 이전 디렉토리로 번역한다. 이 방법이 전체 경로를 기억하고 있다가 타이핑하는 것보다 더 빠르다. 이를 통해 디렉토리를 앞뒤로 매우 효율적으로 이동하게 된다. cd ..cd - 명령어 사이 차이점은 전자(cd ..)는 위로, 후자(cd -)는 아래로 이동하게 위치를 바꾸는 역할을 수행한다. TV 리모컨의 이전 채널 기능으로 생각하면 편하다.

실습해봅시다! ~/Desktop/shell-lesson-data로 이동한다 (이미 이 위치에 있을 것이다).

$ cd ~/Desktop/shell-lesson-data

그런 다음 cd 명령어로 exercise-data/creatures 디렉토리로 이동한다.

cd exercise-data/creatures

cd - 을 실행하면 ~/Desktop/shell-lesson-data로 돌아간 것을 볼 수 있다. cd -를 다시 실행하면 ~/Desktop/shell-lesson-data/exercise-data/creatures로 되돌아간다.

2.5 쉘 명령 일반구문

지금까지 명령어, 선택옵션 및 명령인자를 살펴보았지만 몇 가지 용어를 공식화하는 것이 필요하다. 아래 쉘 명령어를 일반적인 쉘 명령어 사례로 간주하고 구성요소별로 분해하면 다음과 같다:

ls -F /
그림 2.3: 전형적인 쉘 프롬프트

그림 fig-prompt 에서 제시된 쉘 명령어는 ls 명령어, 선택옵션 -F, 명령인자 /로 구성되어 있다. 이미 대시(-) 하나 또는 대시 두개(--)가 명령의 동작을 변경한다. 명령인자는 명령에 작업할 대상(예: 파일 및 디렉토리)을 지정해준다. 선택옵션과 명령인자를 매개변수라고 부른다. 쉘 명령은 둘 이상의 선택옵션과 둘 이상의 명령인자를 사용하여 실행할 수도 있지만, 쉘 명령어 작성에 항상 선택옵션과 명령인자가 필요한 것은 아니다.

선택옵션을 스위치(switches) 또는 플래그(flag)라고 부르는 경우도 있다. 특히 명령인자가 없는 선택옵션을 스위치나 플래그로 부르지만, 선택옵션이라는 용어를 통일해서 사용한다.

쉘 명령어 각 부분은 공백으로 구분된다. ls-F 사이에 공백을 생략하는 경우 공백을 생략하면 쉘은 ls-F라는 명령을 찾지만 이런 명령어는 존재하지 않는다. 쉘 명령어에서 대소문자 구분도 중요하다. 예를 들어 ls -s는 파일 및 디렉토리의 크기를 이름과 함께 표시하지반, ls -S는 아래와 같이 파일과 디렉토리를 크기별로 정렬한다:

cd shell-lesson-data
ls -s exercise-data
total 28
 4 animal-counts   4 creatures  12 numbers.txt   4 proteins   4 writing

ls -s가 반환하는 크기는 블록 단위로 운영 체제마다 다르게 정의되어 있으므로 예제와 동일한 수치를 얻지 못할 수도 있다. 참고로 윈도우 10 운영체제에서 작성되었고, 맥OS이나 리눅스 운영체제에서는 차이가 날 수 있다.

ls -S는 파일과 디렉토리를 크기별로 정렬한다.

$ ls -S exercise-data
animal-counts  creatures  proteins  writing  numbers.txt

이 모든 것을 종합하면 위의 ls -F / 명령은 루트 디렉토리 /에 있는 파일 및 디렉토리 목록을 출력한다. 참고로 윈도우 10 환경에 WSL 우분투 리눅스 환경 사례다. 사용자의 운영체제에 따라 달리 나올 수도 있다.

$ ls -F /
Applications/         System/
Library/              Users/
Network/              Volumes/

예제 2.4 (상대경로 해결) 그림 fig-relative-path 파일시스템 다이어그램에서 만약 pwd 명령어를 쳤을 때, 화면에 \(\text{/Users/thing}\)이 출력된다면, \(\text{ls -F ../backup}\)은 무엇을 출력할까요?

  1. \(\text{../backup: No such file or directory}\)
  2. \(\text{2012-12-01 2013-01-08 2013-01-27}\)
  3. \(\text{2012-12-01/ 2013-01-08/ 2013-01-27/}\)
  4. \(\text{original/ pnas\_final/ pnas\_sub/}\)
그림 2.4: 연습문제 제시된 파일 시스템
정답과 해설
  1. No: backup in /Users 디렉토리 내부에 backup 디렉토리가 있다.
  2. No: Users/thing/backup 디렉토리에 담긴 것을 출력한다. 하지만 ..으로 한 단계 상위 레벨 위를 찾도록 요청했다.
  3. No: 이전 해답을 참조한다.
  4. Yes: ../backup//Users/backup/을 지칭한다.

예제 2.5 (ls 독해 능력) 그림 fig-ex-01 에 나온 디렉토리 구조를 상정한다. 만약 pwd 명령어를 쳤을 때 화면에 \(\text{/Users/backup}\)이 출력되고, -r 인자는 ls 명령어가 역순으로 화면에 출력하게 한다면, 어떤 명령어가 다음을 화면에 출력할까요?

그림 2.5: 연습문제 제시된 파일 시스템
  1. \(\text{ls pwd}\)
  2. \(\text{ls -r -F}\)
  3. \(\text{ls -r -F /Users/backup}\)
정답과 해설
  1. No: pwd 는 디렉토리 명칭이 아님.
  2. Yes: 디렉토리 인자가 없는 ls 명령어는 현재 디렉토리의 파일과 디렉토리를 화면에 출력함.
  3. Yes: 절대 경로를 명시적으로 사용.

2.6 사례: 파일 구성

파일과 디렉토리에 대해서 알았으니, Nelle은 단백질 분석기가 생성하는 파일을 구성할 준비를 마쳤다. 우선 north-pacific-gyre 디렉토리를 생성해서 데이터가 어디에서 왔는지를 상기하도록 한다. 2012-07-03 디렉토리를 생성해서 시료 처리를 시작한 날짜를 명기했다. Nelle은 conference-paperrevised-results같은 이름을 사용하곤 했다. 하지만, 몇년이 지난 후에 이해하기 어렵다는 것을 발견했다. (마지막 지푸라기라도 잡는 심정으로 열심 찾은 것이 revised-revised-results-3 디렉토리를 본인이 생성했다는 것을 발견했을 때였다.)

출력결과 정렬

Nelle은 월과 일에 0을 앞에 붙여 디렉토리를 “년-월-일(year-month-day)” 방식으로 이름지었다. 왜냐하면 쉘이 알파벳 순으로 파일과 디렉토리 이름을 화면에 출력하기 때문이다. 만약 월이름을 사용한다면, 12월(December)이 7월(July) 앞에 위치할 것이다: 만약 앞에 0을 붙이지 않으면 11월이 7월 앞에 올 것이다.

각각의 물리적 시료는 “NENE01729A”처럼 10자리 중복되지 않는 ID로 연구실 관례에 따라 표식을 붙였다. 시료의 장소, 시간, 깊이, 그리고 다른 특징을 기록하기 위해서 수집 기록에 사용된 것과 동일하다. 그래서 이를 각 파일 이름으로 사용하기로 결정했다. 분석기 출력값이 텍스트 형식이기 때문에 NENE01729A.txt, NENE01812A.txt, … 같이 확장자를 붙였다. 총 1,520개 파일 모두 동일한 디렉토리에 저장되었다.

이제 data-shell 현재 작업 디렉토리에서 Nelle은 다음 명령어를 사용해서, 무슨 파일이 있는지 확인할 수 있다:

$ ls north-pacific-gyre/2012-07-03/

엄청나게 많은 타이핑이지만 탭 자동완성(tab completion)을 통해 쉘에게 많은 일을 시킬 수도 있다. 만약 다음과 같이 타이핑하고:

$ ls nor

그리고 나서 탭(키보드에 탭 키)을 누르면, 자동으로 쉘이 디렉토리 이름을 자동완성 시켜준다:

$ ls north-pacific-gyre/

Tab 을 다시 누르면, Bash가 명령문에 2012-07-03/을 추가하는데, 왜냐하면 유일하게 가능한 자동완성조건이기 때문이다. 한번더 탭을 누려면 아무것도 수행하지 않는다. 왜냐하면 1520가지 경우의 수가 있기 때문이다. 탭을 두번 누르면 모든 파일 목록을 가져온다. 이것을 탭 자동완성(tab completion)이라고 부르고, 앞으로도 다른 많은 툴에서도 많이 볼 것이다.

그런 다음 Nelle이 G를 누른 다음 Tab 키를 다시 누르면 ’g’로 시작하는 모든 파일이 처음 세 글자인 ’goo’를 공유하기 때문에 쉘이 자동으로 ’goo’를 추가한다.

$ ls north-pacific-gyre/goo

모든 파일을 보려면 Tab 키를 두 번 더 누르면 된다.

$ ls north-pacific-gyre/goo
goodiff.sh   goostats.sh

도움말

유닉스 쉘 명령어를 처음 접하게 되면 암호스럽게 느껴진다. 이런 경우 해당 작업을 하는 명령어를 챗GPT를 활용하여 도움말을 얻을 수 있고 더 나아가 바로 실행도 가능하다. 실행명령어로 E를 누르게 되면 영어로 작성된 ls 명령에 대한 도움말이 여러 페이지에 걸쳐 화면에 전개된다. 빠져나오고자 하는 경우 키보드 q 를 눌러 도움말 보기를 중단한다.

프롬프트: ls 명령어에 대한 도움말을 얻고 싶습니다.

$ sgpt -s "ls 명령어에 대한 도움말을 얻고 싶습니다."
man ls
[E]xecute, [D]escribe, [A]bort: D
The "ls" command is used to list the files and directories in a specified directory.
[E]xecute, [D]escribe, [A]bort: E

챗GPT가 프롬프트로 작성한 유닉스 쉘 명령어를 해석하면 다음과 같다.

“ls” 명령은 지정된 디렉토리에 있는 파일과 디렉토리를 나열하는 데 사용된다.

sgpt 프롬프트를 실행하게 되면 ls 명령어에 대한 매뉴얼이 화면가득 출력된다. 빠져나오고자 할 경우 키보드 q를 눌러 빠져나온다.

wsl -bash: man: command not found

man 유닉스 명령어를 실행할 수 없는 경우가 종종 있다. 이런 경우 man-db 패키지를 설치하면 된다.

$ sudo apt-get update
$ sudo apt-get install man-db

다른 디렉토리 탐색

현재 디렉토리가 아닌 그 하위 디렉토리에 어떤 파일과 디렉토리가 담겨있는지 궁금한 경우가 있다. 이런 경우도 자연어로 디렉토리 명칭을 지정하면 챗GPT가 유닉스 명령어를 생성해주고 즉시 실행시킬 수 있다.

프롬프트: north-pacific-gyre 디렉토리 아래 파일과 디렉토리 내용을 보고 싶습니다.

$ sgpt -s "north-pacific-gyre 디렉토리 아래 파일과 디렉토리 내용을 보고 싶습니다."
ls north-pacific-gyre
[E]xecute, [D]escribe, [A]bort: E
goodiff.sh      NENE01729B.txt  NENE01751B.txt  NENE01843B.txt  NENE01978B.txt  NENE02040B.txt  NENE02043B.txt
goostats.sh     NENE01736A.txt  NENE01812A.txt  NENE01971Z.txt  NENE02018B.txt  NENE02040Z.txt
NENE01729A.txt  NENE01751A.txt  NENE01843A.txt  NENE01978A.txt  NENE02040A.txt  NENE02043A.txt

챗GPT가 프롬프트로 작성한 유닉스 쉘 명령어를 해석하면 다음과 같다.

north-pacific-gyre 디렉토리 아래 파일과 디렉토리 내용을 보고 싶습니다.

실행하게 되면 north-pacific-gyre 디렉토리 내에 포함된 파일과 디렉토리를 화면에 출력한다.

현재 디렉토리 위치 확인

유닉스 운영체제는 파일과 디렉토리로 구성되어 있다. 한참 작업을 하다보면 작업하는 파일과 디렉토리가 혼동되는 경우가 종종 있다. 이런 경우 현재 자신의 위치를 파악하는 것이 중요하다. 이런 경우에 유닉스 쉘 명령어가 기억나지 않는다면 sgpt -s 를 통해 유닉스 명령어를 찾고 즉시 실행시켜 현재 디렉토리 위치를 파악할 수 있다.

프롬프트: 현재 위치가 어디인지 알고 싶습니다.

$ sgpt -s "현재 위치가 어디인지 알고 싶습니다."
pwd
[E]xecute, [D]escribe, [A]bort: D
Print the current working directory.
[E]xecute, [D]escribe, [A]bort: E
/mnt/c/Users/statkclee/Desktop/shell-lesson-data

챗GPT가 프롬프트로 작성한 유닉스 쉘 명령어를 해석하면 다음과 같다.

현재 작업 디렉토리를 화면에 출력합니다.

sgpt 프롬프트 실행결과는 현재 작업 디렉토리 위치를 화면에 출력한다.