개요

엔지니어들은 게으름에서 비롯된 이상한 습성을 가진 경우가 있다. 정말 하기 싫은 일이 있으면 엔지니어들은 자신을 대신해 이 일을 해줄 무언가를 만든다. 심지어 이런 것을 만드는 데 걸리는 노력이 원래 하기 싫은 일을 하는 데 드는 노력보다 훨씬 많이 들어도 굳이 이런 짓을 하고는 한다.
한 권으로 읽는 컴퓨터 구조와 프로그래밍 p. 196

그간 고민하고 있던 블로그 플랫폼을 Github Pages로 옮기게 되었습니다. 그나마 익숙한 Jekyll을 사용해서 만들었습니다. Jekyll은 포스트를 날짜-파일제목.md 형식으로 관리하는데요, 저는 이 파일을 만드는 과정이 제법 귀찮게 느껴졌습니다. 요즘 날짜 감각이 없어져서 파일을 생성할 때마다 매번 시간 보는 게 귀찮았거든요. 게다가 저는 _posts 디렉터리에서 연도/월 형식으로 디렉터리를 만들어서 포스트를 관리하려고 했기 때문에 손이 조금 더 갔습니다.

개발자는 귀찮으면? 자동으로 해주는 걸 만들자!

이러한 의식의 흐름으로 Jekyll 포스팅 파일 생성기를 셸 스크립트로 만들었습니다. 그리고 이 글은 셸 스크립트를 만드는 과정을 담았습니다.

만들려는 셸 스크립트의 동작은 이렇습니다.

  1. 명령어를 실행하는 오늘 날짜를 기준으로 연도/월 디렉터리를 생성합니다.
  2. 인수로 파일 이름을 입력받고, 연도/월/연도-월-일-파일이름.md 파일을 생성합니다.
  3. vscode로 만든 파일을 엽니다.

🗂 연도/월 디렉터리 생성

파일을 먼저 만들어봅시다. 파일은 편한 곳에 만들면 되는데, 나중에 alias로 등록해서 사용할 거니까 홈 디렉터리가 아니더라도 접근하기 좋은 곳에 만들어줍니다. 저는 홈 디렉터리에 만들었습니다.

$ touch post.sh

파일을 만들었으면 실행 권한을 설정합니다.

$ chmod u+x post.sh

이제 셸 스크립트 파일을 열어서 코드를 작성합니다. 첫 줄은 셸 경로를 적습니다. 일반적으로 다음과 같이 작성합니다.

#!/bin/sh

자, 이제 우리가 만든 셸 스크립트 파일은 파일을 생성하려는 위치가 아니라 홈 디렉터리에 있잖아요? 그래서 파일을 생성할 위치를 찾아야 합니다. 터미널로 본인의 블로그 디렉터리에서 포스트를 관리하는 디렉터리까지 들어갑니다. Jekyll_posts 디렉터리에 포스트를 작성하니까 그곳으로 들어가서 pwd 명령어를 실행합니다.

pwd 명령어는 현재 위치한 곳의 경로를 알려주는 명령어입니다.

$ pwd
/Users/jiwon/Projects/jwonyLee.github.io/_posts

제 블로그 디렉터리 경로는 저렇습니다. 이건 본인의 디렉터리 경로마다 다르니까 참고만 하세요. 아무튼, 이렇게 얻은 경로를 복사해서 셸 스크립트에 변수로 만들어줍니다.

#!/bin/sh

postPath="/Users/jiwon/Projects/jwonyLee.github.io/_posts"

참고로 셸 스크립트에서 = 사이에 띄어쓰기가 있으면 인식을 못 합니다. 예를 들어, postPath = "...." 이렇게 작성하면 제대로 동작하지 않으니 주의해서 작성합니다.

디렉터리를 생성하려면 오늘 날짜가 필요합니다. 년, 월이 따로따로 필요하고, 이후에도 파일을 생성할 때 사용할 예정이기 때문에 일도 포함하여 변수로 만들어 둡니다.

현재 시각을 표시하는 명령어는 date 명령어입니다.

# 오늘 날짜 구하기
currentYear=$(date, '+%Y')
currentMonth=$(date, '+%m')
currentDay=$(date, '+%d')

디렉터리를 만드는 데 필요한 정보는 모두 구했습니다. 이제 디렉터리를 만들어봅시다. 저는 년/월 형태로 포스트를 관리할 것이기 때문에 ../_posts/year/month 형태로 디렉터리를 만들 예정입니다. 년/월 디렉터리가 필요 없으면 이 부분은 건너뛰어도 됩니다.

디렉터리를 만드는 명령어는 mkdir입니다.

-p 옵션은 인수에 지정한 디렉터리 경로가 존재하지 않으면 그 중간에 있는 디렉터리도 포함해서 새로운 디렉터리를 만듭니다. 예를 들어, 2021 디렉터리가 없으면 2021 디렉터리를 포함해서 2021/08 디렉터리를 만든다는 뜻입니다.

# 오늘 날짜에 맞는 디렉터리 생성
mkdir -p $postPath/$currentYear/$currentMonth

💾 연도/월/연도-월-일-파일이름.md 파일 생성

인수로 파일명과 제목으로 쓸 문자열도 받아봅시다.

명령어 인수는 특수 변수 $1, $2, $3…을 사용합니다.

$ ./post.sh "File Generator"
# 파일명/제목을 인수로 받음
postTitle=$1

인수로 들어온 "File Generator"를 postTitle 변수에 할당합니다. 큰따옴표로 묶지 않으면 띄어쓰기를 했을 때 인수가 띄어쓰기를 기준으로 들어오기 때문에 큰따옴표로 묶어서 인수를 작성합니다.

이렇게 입력받은 postTitle을 바로 쓸 수 있으면 좋겠지만, 파일명에 띄어쓰기가 들어가는 건 원하지 않기 때문에 필터링해줄 겁니다. 한글, 영어, 숫자를 제외한 특수문자는 거르고 띄어쓰기는 -로 변환합니다. 여기서는 sed 명령어를 사용했습니다.

sed 명령어에 대한 자세한 내용은 sed command in linux로 검색해보세요.

# 제목을 파일명에 쓸 수 있게 필터링
postTitle=$1
filterPostTitle=$(echo $postTitle | sed 's/[^a-z,A-Z,0-9,가-힣,[:space:]]//g' | tr " " "-")

위에서 구한 오늘 날짜와 filterPostTitle을 조합해서 파일명을 변수로 만듭니다. 저는 마크다운 파일을 만들 거라서 .md를 뒤에 붙여줬는데, 원하는 확장자로 변경해서 작성합니다. txt 파일을 만들 거면 .txt 로 바꾸면 됩니다.

# 오늘 날짜 + filterPostTitle로 파일 이름 생성
fileName=$currentYear"-"$currentMonth"-"$currentDay"-"$filterPostTitle".md"

거의 다 왔어요! 파일 내부에 들어갈 내용을 작성합니다. 빈 파일을 만들고 싶다면 이 부분은 생략해도 좋아요. 저는 Jekyll에서 frontMatter 부분을 작성할 거예요. 추가로 아까 입력받았던 postTitle을 title에 작성했습니다.

# 파일 상단에 들어갈 내용
frontMatter="---
layout: post
title: $postTitle
subtitle:
categories:
tags: []
publish: false
---"

파일명도 만들었고, 파일에 채울 내용도 만들었으니 파일을 만들어봅시다.

# 파일 생성
newFilePath=$postPath/$currentYear/$currentMonth/$fileName
echo "$frontMatter" > $newFilePath

frontMatter를 큰따옴표로 묶어준 이유는, 줄 바꿈을 포함해서 작성하고 싶어서입니다. 여기까지 작성하고 셸 스크립트를 실행해보면 원하는 경로에 파일이 생성된 걸 볼 수 있어요!

$ ./post.sh "File Generator"
/Users/jiwon/Projects/jwonyLee.github.io/_posts/2021/08/2021-08-20-File-Generator.md

✍️ 에디터로 파일 열기

파일을 생성한 목적이 글을 쓰기 위해서니 에디터로 파일을 여는 것까지 셸 스크립트에 작성합니다. 저는 vscode로 글을 쓰기 때문에 vscode로 열리게 했어요. 원하는 에디터 실행 명령어를 쓰면 됩니다. (예: vi $newFilePath)

# 에디터로 열기
code $newFilePath

전체 코드

이제 셸 스크립트를 실행하면 디렉터리 생성 + 파일 생성 + 에디터로 열기까지 한 번에! 🥰

⚡️ 명령어 등록

매번 홈 디렉터리에 가서 ./post.sh을 실행할 수는 없는 모양이잖아요? 현재 위치에 상관없이 실행할 수 있으면 좋겠죠. 셸 스크립트 실행 명령어를 alias로 지정하면 됩니다.

보통은 ~/.bashrc에 등록을 하는데요, 저는 zsh를 쓰고 있어서 ~/.zshrc에 등록할게요. ~/.zshrc를 열고 하단으로 내리면 alias 작성 예시가 있어요! 그 아래 줄에 작성합니다. 저는 post 키워드로 실행할 수 있게 해줄 거 에요. 키워드도 원하는 대로 작성하면 되는데, OS 명령어와 겹치는 건 안 좋겠죠?

alias post="~/post.sh"

저장하고 나와서 다음 명령어도 실행합니다.

$ source ~/.zshrc

이제 post.sh를 일일이 붙일 필요 없이, 아무데서나 post 명령어로 만들었던 셸 스크립트를 실행할 수 있어요!

$ post "File Generator"

💬 마무리

_posts/연도/월/file.md 구조 말고도 원하는 디렉터리 이름을 인수로 받아서 _posts/category/file.md 구조로 만들 수도 있어요. 이건 약간만 응용하면 되니까 따로 첨부하지는 않을게요.

오늘은 Jekyll 블로그에 포스팅할 때마다 매번 마크다운 파일을 생성하는 불편함을 해결하기 위해서 셸 스크립트를 만드는 과정을 작성해봤습니다. 도움이 되셨나요? 도움이 되셨다면 구독과 좋아요가 아니고 리액션 한 번씩만 눌러주세요!

그럼 안녕! 👋

참고 자료

  • 리눅스 입문자를 위한 명령어 사전