자주 쓰는 명령어 메모다. 다만 예전 메모를 그대로 옮기기 전에 정정할 게 두 가지 있었다.
exa는 이제 eza다
예전 메모는 ls 대체로 exa를 추천했다. 지금 exa 저장소의 README 첫 줄은 이렇게 되어 있다.
exa is unmaintained, use the fork eza instead.
저장소가 archive 처리조차 안 된 이유도 README에 나온다: “이 저장소가 archive되지 않은 건, archive할 권한을 가진 유일한 사람과 연락이 닿지 않기 때문이다.” 관리자가 사라져 마지막 정리조차 못 하는 상태이니, 지금 exa를 새로 설치하면 유지보수가 끊긴 소프트웨어를 까는 셈이다. 대안은 커뮤니티가 이어받은 fork eza다. 명령어는 거의 호환된다.
실제로 값어치를 하는 것
나머지 도구를 전부 나열하기보다, 어떤 걸 왜 쓰는지만 적는다.
- ripgrep(
rg), fd — 둘 다 기본으로.gitignore를 존중해node_modules나 빌드 산출물을 따로 제외할 필요가 없고, 체감 속도도 빠르다. - bat —
cat에 문법 강조와 페이저(pager)가 붙는다. 긴 설정 파일이나 코드를 훑어볼 때만 골라 쓴다. - hexyl, procs — 있으면 편하지만 없어도
od,ps로 대체된다. 취향의 영역이다.
설치할 때 걸리는 것
우분투/데비안에서 bat, fd는 이름이 이미 다른 패키지가 쓰고 있어 실행 파일 이름이 바뀐다. bat README에 따르면 구버전 배포판은 bat 대신 batcat으로 설치되고(최신 배포판은 bat 그대로), fd README는 패키지명이 아예 fd-find고, 이미 다른 패키지가 fd를 쓰고 있어 실행 파일도 fdfind로 바뀐다고 설명한다(단, 이 프로젝트가 직접 배포하는 .deb 릴리스는 실행 파일명이 fd 그대로다). 둘 다 심볼릭 링크로 통일한다.
mkdir -p ~/.local/bin
ln -s /usr/bin/batcat ~/.local/bin/bat # batcat으로 설치된 경우
ln -s $(which fdfind) ~/.local/bin/fd스크립트에는 고전 도구를 쓴다
대화형 쉘에서 편하다고 스크립트에도 eza, fd, bat를 넣지는 않는다. 남의 서버·CI 컨테이너에는 기본으로 없다. 스크립트는 ls, find, cat처럼 어디에나 있는 고전 도구로 짜고, 새 도구는 터미널에 앉아 있을 때만 쓴다.
오래된 로그 지우기
예전 메모는 10일 지난 로그를 이렇게 지웠다.
find -name '*.log' -mtime +10 | xargs rm세 군데가 틀렸다.
1) 공백이 있는 파일명에서 깨진다. xargs는 기본적으로 공백을 구분자로 본다. b with space.log 하나를 넣고 확인하면 파일 하나가 인자 세 개(./b, with, space.log)로 쪼개진다.
$ find . -name '*.log' -mtime +10 -type f | xargs sh -c 'echo "got $# args:"; printf " [%s]\n" "$@"' _
got 3 args:
[./b]
[with]
[space.log]-print0 / xargs -0으로 널 문자(\0) 구분자를 쓰거나, find에 내장된 -delete를 쓰면 안전하다.
find . -name '*.log' -mtime +10 -type f -print0 | xargs -0 rm
find . -name '*.log' -mtime +10 -type f -delete # 더 간단2) -type f가 없으면 디렉터리도 걸린다. *.log라는 이름의 디렉터리를 만들고 mtime을 15일 전으로 맞춘 뒤 확인했다.
$ find . -name '*.log' -mtime +10 # -type f 없음
./b with space.log
./c.log # 디렉터리도 걸린다
$ find . -name '*.log' -mtime +10 -type f
./b with space.log # 파일만플레인 rm은 디렉터리를 못 지워 에러로 끝나지만, rm -r/rm -rf였다면 디렉터리 전체가 조용히 사라진다.
3) -mtime +10은 “10일 초과”가 아니다. GNU findutils 매뉴얼에 따르면 find는 파일 나이(초)를 86400으로 나눈 뒤 소수점을 버린 정수로 비교하고, +10은 그 정수가 10보다 큰 것을 뜻한다. 10.9일 된 파일은 정수 10으로 절삭되어 걸리지 않는다 — 만 11일(정수 11)이 되어야 +10에 걸린다.
지우기 전에는 -delete를 -print로 바꿔 뭐가 걸리는지 먼저 확인하는 습관을 들인다. 참고로 -ctime은 “생성 시각”이 아니라 inode 메타데이터가 바뀐 시각(권한 변경 등도 포함)이니 혼동하지 않는다.
로그는 사실 logrotate가 답이다
find + -delete는 logrotate가 관리하지 않는 로그를 일회성으로 정리할 때 쓰는 임시방편이다. 상시 운영 중인 서비스라면 매번 손으로 지우기보다 /etc/logrotate.d/에 설정을 넣어 회전·압축·보관 기간을 맡기는 쪽이 맞다.
참고
- ogham/exa — README 첫 줄의 유지보수 중단 안내와 archive되지 않은 이유를 확인했다.
- eza-community/eza — exa를 이어받은 커뮤니티 fork임을 확인했다.
- sharkdp/bat — 우분투/데비안 구버전의
batcat이름을 확인했다. - sharkdp/fd — 패키지명
fd-find, 실행 파일명fdfind를 확인했다. - GNU findutils 매뉴얼 — Comparing Timestamps —
-mtime이 나이를 86400초로 나눈 뒤 정수로 절삭해 비교한다는 동작을 확인했다.