Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 채보
- C
- C#
- 명령어
- Visual Studio
- error
- 핑거스타일
- Docker
- 프로그래머스
- C++
- 오류
- SSH
- pandas
- JSON
- Python
- Linux
- VS Code
- label
- LIST
- 기타 연주
- pytorch
- paramiko
- mysql
- Selenium
- OpenCV
- pip
- YOLO
- ubuntu
- Numpy
- windows forms
Archives
- Today
- Total
기계는 거짓말하지 않는다
Linux ls 명령어 구현 (1) 본문
ls의 옵션 중 –l, -a, -R, -al, -aR, 파이프(-pi)를 구현
코드의 전문이 아닌 일부만 서술
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
typedef struct info_set { // 파일의 세부정보 저장을 위한 구조체
long link; // 하드링크 개수
long size; // 파일 크기
long time[4]; // 최종상태 변경시간
char permission[11]; // 권한
char * UID; // 사용자 ID
char * GID; // 그룹 ID
char * fname; // 파일 이름
char sympath[512]; // 심볼릭 링크 원본 파일 경로
} info_set;
파일의 세부정보 저장을 위한 구조체를 선언한다.
구현되어야 할 함수들은 다음과 같다.
void lsOption(char **, char *, char *, int); // 옵션 판별
void lsPipe(char *, char *, char *); // 파이프 -pi 구현
void listDir(char *, char *, int); // 옵션에 따라 사용할 함수 결정
void sort(char **, int); // 정렬
void isLower(char *, char *); // 대문자를 소문자로 바꿈
void printDirND(char **, char *, int, int); // 파일이름 출력
void printDirD(char **, char *, int, int); // 파일이름과 세부정보 출력
void maxWidthCalc(info_set *, int *); // 문자,숫자 너비 계산
void setInfo(info_set *, char *, char *); // 세부정보 저장
char * convertMonth(int); // 숫자 월 정보를 영어 약자로 리턴
void lsRecurse(char *, int); // -R 기능
void menual(void); // 사용법
void memoryAllocFail(void); // 메모리 할당 실패시 오류 내용 출력
main 함수에서 실행한 명령에 따라 옵션을 분리한다.
int main(int argc, char * argv[]) {
char * dir;
int op; // 0 = no op, 1 = option
if(argc == 1) { //현재 디렉터리
op = 0;
dir = ".";
listDir(dir, NULL, op);
}
else {
...
}
...
}
listDir 함수에서 명령어에 따라 함수 호출을 분기한다.
void listDir(char *dir, char * option, int op) {
DIR * dp;
struct dirent *d;
char ** list;
int cnt = 0, i;
if((dp = opendir(dir)) == NULL) {
perror(dir);
exit(1);
}
while((d = readdir(dp)) != NULL) // 파일 개수
cnt++;
rewinddir(dp); // 디렉터리 스트림 위치 처음으로
list = (char**)malloc(sizeof(char*) * cnt); // 파일의 개수만큼 동적할당
if(list == NULL) memoryAllocFail();
d = readdir(dp);
for(i = 0; d != NULL; i++) {
list[i] = d->d_name;
d = readdir(dp);
}
sort(list, cnt); // 정렬
switch(op) {
case 0:
printDirND(list, dir, 0, cnt);
break;
case 1:
lsOption(list, dir, option, cnt);
break;
default:
puts("Error");
return;
}
closedir(dp);
free(list); // 메모리 할당 해제
}
lsOption 함수에서 상세 옵션에 따라 다른 함수를 호출한다.
void lsOption(char ** list, char * dir, char * option, int cnt) {
if(strlen(option) == 2 && option[1] == 'a') // ls -a
printDirND(list, dir, 1, cnt); // 파일 이름만 출력
else if(strlen(option) == 2 && option[1] == 'l') // ls -l
printDirD(list, dir, 0, cnt); // 세부 정보 출력
else if((strlen(option) == 3 && option[1] == 'l' && option[2] == 'a') || (strlen(option) == 3 && option[1] == 'a' && option[2] == 'l')) // ls -al or ls -la
printDirD(list, dir, 1, cnt);
else if(strlen(option) == 2 && option[1] == 'R') // -R
lsRecurse(dir, 0);
else if((strlen(option) == 3 && option[1] == 'a' && option[2] == 'R') || (strlen(option) == 3 && option[1] == 'R' && option[2] == 'a')) // ls -aR or ls -Ra
lsRecurse(dir, 1);
else {
puts("사용법은 ./filename help 를 입력하세요");
return;
}
}
printDirND 함수는 자세하게 출력하지 않으며, printDirD 함수는 -l과 같은 옵션에서 세부 정보를 출력한다.
void printDirND(char ** list, char * dir, int hide, int cnt) { // hide = 1 일때 숨김 파일 표시
struct stat buf;
char * path;
char temp[512];
char npath[512];
int i, len, hidecnt = 0;
len = strlen(dir);
if(dir[len - 1] != '/' && len != 1) { // /를 입력하지 않았을 경우
strcpy(npath, dir);
strcat(npath, "/");
dir = npath;
}
for(i = 0; i < cnt; i++) {
if(list[i][0] == '.' && hide == 0) { hidecnt++; continue; } // 숨김 파일일 경우
path = list[i]; // 현재 디렉터리일 경우 파일 이름으로 경로 설정
if(dir[0] != '.' || strlen(dir) > 1) { // ./dir or dir/ or ../ or dir 사용가능
strcpy(temp, dir);
path = strcat(temp, list[i]); // 다른 디렉터리일 경우 경로에 파일이름을 붙임
}
if(lstat(path, &buf) < 0) {
perror("lstat()"); // 파일 상태정보 가져오기 실패
return;
}
else {
if(S_ISDIR(buf.st_mode)) {
printf("\x1b[36m%s ", list[i]); // 디렉터리 파란색 출력
printf("\x1b[0m");
}
else if(S_ISLNK(buf.st_mode)) {
printf("\x1b[35m%s ", list[i]); // 심볼릭 링크 분홍색 출력
printf("\x1b[0m");
}
else
printf("%s ", list[i]);
}
}
if(cnt-hidecnt > 0)
puts("");
}
printDirD 함수는 아래와 같이 출력되게 한다.
'Linux' 카테고리의 다른 글
Ubuntu 18.04 LTS Install OpenCV (0) | 2022.04.15 |
---|---|
Linux ls 명령어 구현 (2) (0) | 2021.08.17 |
Linux VI Editor 기타 명령어 (0) | 2021.06.30 |
Linux VI Editor 검색, 문자열 변경 명령어 (0) | 2021.06.30 |
Linux VI Editor 편집, 저장, 이동 명령어 (0) | 2021.06.30 |
Comments