디렉토리 다루기(9-1)
- mkdir,rmdir
- opendir,closedir
- readdir
- rewinddir
- chdir
- getcwd
mkdir, rmdir
* 삭제는 빈 디렉토리만 가능함
<sys/types.h> <sys/stat.h>
int mkdir(const char *pathname, mode_t mode)
int rmdir(const char* pathname)
성공하면 0, 실패하면 -1 을 반환한다.
디렉토리를 생성하고 그냥 ls를 했을 때는 아무것도 안나오지만,
ls -a 로 히든파일까지 모두 보면 . 과 .. 이 나온다.
이는 현재디랙토리와 부모디렉토리를 가리키는데,
이들의 생성/수정시간을 보면
해당 디렉토리가 생성된 시간으로 나와있다.
* 부모 디렉토리를 가리키는 .. 또한 현 디렉토리 생성 시간으로 시간이 설정되어 있다.
그리고 해당 디렉토리를 파일을 생성하는 등 수정하면
해당 디렉토리를 가리키는 . 은 수정한 시간에 맞추어 시간이 변경되고,
부모디렉토리는 이와 반대로 디렉토리 생성시간으로 되어 있다.
그리고 해당 디렉토리의 부모 디렉토리로 이동해서 ls 를 해보면, 해당 디렉토리는
최근 수정된 시간으로 .과 같이 시간이 바뀌어있다.
mkdir 함수를 사용해서 디렉토리를 생성하는 프로그래밍 만들기
그냥 명령어를 사용해서 터미널에 mkdir dirname 으로 파일을 만들면 기본적으로
rwxr-xr-x 가 나온다.
메인함수에서 int argc, char * argv[] 를 받아서 인자가 2보다 작으면 나가고 (-1),
아니면 mkdir로 인자에 해당하는 이름의 디렉토리 만든다.
int main(int argc, char* argv[]) {
if(argc < 2) exit(-1);
mkdir(argv[1], 0755);
}
그런데 만약에 mkdir 2번째 인자에 아무것도 들어있지 않으면, 에러가 발생한다.
opendir, closedir
<sys/types.h> <dirent.h>
DIR* opendir(const char* pathname);
int closedir(DIR* dir);
opendir을 사용하면 해당 디렉토리 이름에 해당하는 디렉토리 포인터를 반환한다.
closedir은 디렉토리 포인터가 필요하고, 해당 포인터가 가리키고 있는 디렉토리를 닫느나.
Onpendir은 성공하면 DIR 포인터를 반환하고, 실패하면 NULL을 반환한다.
closedir은 성공하면 0을 반환하고, 실패하면 -1을 반환한다.
opendir("."), opendir("..") 과 같이 현재디렉토리, 부모디렉토리를 열수도 있다.
<sys/types.h> <dirent.h>
int main() {
DIR* dir;
if ((dir = opendir(".")) == NULL) {
perror(".");
exit(1);
}
closedir(dir);
}
readdir
<sys/types.h>
<dirent.h>
struct dirent* readdir(DIR* dir);
호출해 성공해서
해당 dir 포인터가 가리키고 있는 디렉토리에 dirent 엔트리가 존재하는 경우 struct dirent 포인터 타입의
디엑토리 엔트리를 반환한다.
더이상 읽은 디렉토리 엔트리가 없다면 NULL을 반환한다.
DIR* 은 디렉토리를 가리키는 포인터고
struct dirent* 는 뭐냐면 디렉토리 엔트리 구조를 가지고 있는 포인터이다.
이 struc dirent는 아래와 같은 구조를 가진 구조체이다.
struc dirent {
long d_ino; // i node number
char d_name[NAME_MAX + 1] // NAME은 "\O"을 포함한 값이기 때문에 NAME_MAX + 1
}
inodenum | namechar[0] | namechar[1] | ... | namechar[n] | \0 | |
1200 | t | e | s | t | 1 | \0 |
이 구조체는 readdir에서 반환된 값인데, dirent 포인터가 가리키고 있는 inode와 name을 포함한 구조체를 읽는다.
만약 포인터가 1200을 가리키고 있다면 해당 구조체에 해당하는 구조체를 읽어오는 것이다.
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
DIR* dir;
struct dirent* den;
if((dir = opendir(".")) == NULL) exit(1);
while((den = readdir(dir)) != NULL){
printf("%s\n", den->d_name);
}
closedir(dir);
}
이렇게 열어서 바로 읽게되면 가장 위에 있는 dirent을 포인터가 가리키고 있다. 그래서 위에서부터
while문을 읽으며 읽는다.
그리고 이렇게 readdir을 사용해서 읽게되면,
기존 ls에서 -a옵션을 주어야 볼 수 있는 히든 파일도 모두 볼 수 있다.
그리고 dirent 구조체 내에 있는 것들은 알파벳 순서대로 정렬되어 있지 않다.
그래서 ls 명령어에 따른 결과값처럼 출력하려면 따로 정렬을 해주어야 한다.
rewinddir
<sys/types.h> <dirent.h>
void rewinddir(DIR* dir);
반환 값을 따로 없다.
개방된 디렉토리의 읽기 포인터 위치를 처음으로 되돌린다.
디렉토리 dir table에 있는 각 inode에 dirent 구조체를 가리키고 있는 포인터가
이 구조체를 읽거나 하면서 포인터가 가리키는 위치가 변하게 되는데,
이를 다시 처음으로 되돌리고자 할 때 사용한다.
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
DIR* dir;
struct dirent* den;
if((dir = opendir(".")) == NULL) exit(1);
while((den = readdir(dir)) != NULL) {
printf("%s\n", den->d_name);
}
rewinddir(dir);
while((den = readdir(dir)) != NULL) {
printf("%s\n", den->d_name);
}
closedir(dir);
}
chdir
<unistd.h>
int chdir(const char* path);
현재 작업 디렉토리를 변경한다.
성공하면 0을 반환하고, 실패하면 -1을 반환한다.
chdir은 이를 호출한 현제 프로그램에서만 적용된다. (현체 코드를 돌리고 있는 프로세스에서만)
하나의 프로그램은 shell의 자식 프로세스이며, 이 프로그램(프로세스)에서만 적용되고
shell 프로세스는 변하지 않는다.
shell도 프로세스이지만, 프로그램을 돌린 shell의 자식 프로세스를 shell이 생성함
이렇게 생성한 자식 프로세스에서만 cwd가 변한다.
+ 자식 프로세스는 처음에 부모프로세스의 cwd를 받아서 부모 프로세스와 같으나,
chdir을 사용하여 자식프로세스의 cwd를 바꾼다.
file1 = open("tmp/file1.txt", O_RDONLY);
file2 = open("tmp/file2.txt", O_RDONLY);
// 위와 같이 디렉토리 안에 있는 다수의 파일에 접근할 때
chdir("tmp");
file1 = oepn("file1.txt", O_RDONLY);
file2 = open("file2.txt", O_RDONLY);
// 위와 같이 현재 작업 디렉토리 변경해서 접근 가능
getcwd
<unistd.h>
char *getcwd(char* buf, size_t size);
현재 디렉토리의 절대 경로를 반환한다.
경로를 반환 받기 위해서 파라미터로 경로를 저장한 버퍼와, 버퍼의 사이즈를 받는다.
성공하면 buf의 포인터를 반환하고,
(char*인 buf를 받아야하는 포인터를 반환하기 때문에 char* 타입의 함수)
(+ char 타입의 포인터를 가지고 있는 buf를 반환하기해
char 타입의 포인터를 선언해서 char 포인터 크기 만큼 값을 반환 받을 수 있음)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 256
void printcwd() {
char buf[BUF_SIZE];
if (getcwd(buf, BUF_SIZE) == NULL) exit(1);
printf("%s\n", buf);
}
int main() {
printcwd();
chdir("..");
printcwd();
}