【シェルスクリプト】shファイルでテンプレートファイルを作成する。


## 当該記事について
学習用の簡易ページを毎回手作業で作成するのが面倒になったので学習も兼ねてshファイルで作成できるようにしました。
その際のメモとなります。
# 要件

1.テンプレートから新規ページを作成する。
2.ホームページから作成したページにリンクで飛べる様にする。
3.作成したページのヘッダーからホームページに戻れるようにする。
4.リンク名(ページタイトル)はコマンドの引数で指定する。
5.作成ファイルのフォルダ階層をコマンドの引数で指定する。
6.ファイル名をコマンドの引数で指定する。

### イメージ
![4b191577fe9a5c409bbcbe3c60908781.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/47fe03a1-4084-2a9d-59b5-9c3c566b836b.gif)

## フォルダ階層

初期のフォルダ階層
```
.
├── cm
│   ├── makePage.sh (このファイルを作る)
│   └── temp.html (テンプレート)
└── src
    └── component (このディレクトリ配下に新規ファイルを作成)
        ├── home.html (ホームページ)
        └── one
            └── two
                ├── first.html
                └── second.html
```
### ホームページ
```home.html
<html>

<body>
  <h1>HOME</h1>
  <div> <a href="./one/two/first.html">最初のページ</a></div>
  <div> <a href="./one/two/second.html">２番目のページ</a></div>
  <!-- toHomeLinkPath -->
  <!-- ↑ここにリンクを追記します。 -->
</body>

</html>
```
### ホームページ
```temp.html
<!DOCTYPE HTML>
<html>

<body>
  <div id="page-header">
    <a href="toHomeLinkPath">HTML HOME</a><span id="btns"></span><span id="mInfo"></span>
    <!-- ↑ここを修正してホームへのリンクを作成します。 -->
  </div>
  <h1>
    <!-- page title -->
    <!-- ↑ここにタイトルを表示します。 -->
  </h1>
</body>

</html>

<style>
  /* 略 */
</style>
```
### shファイル
```makePage.sh
#!/bin/sh

CREATED_FILE_PATH="../src/component"
DYNAMIC_DIR_PATH="${CREATED_FILE_PATH}"

for VAR in "${@:1:($#-2)}" ;
  do
    DYNAMIC_DIR_PATH="${DYNAMIC_DIR_PATH}/${VAR}"
    TO_PAGE_LINK="${TO_PAGE_LINK}/${VAR}"
    mkdir $DYNAMIC_DIR_PATH
    TO_HOME_LINK="..\/${TO_HOME_LINK}"
  done

FILE_NAME="${@:($#-1):1}.html"
TITLE="${@:($#):1}"

TO_PAGE_LINK=".${TO_PAGE_LINK}/${FILE_NAME}"

CREATED_FILE_PATH="${DYNAMIC_DIR_PATH}/${FILE_NAME}"

TO_HOME_LINK="${TO_HOME_LINK}home.html"

cp "./temp.html" $CREATED_FILE_PATH

LINK_TAG="<div> <a href=\"${TO_PAGE_LINK}\">${TITLE}<\/a><\/div>"

gsed -i "s/toHomeLinkPath/${TO_HOME_LINK}/g" $CREATED_FILE_PATH
gsed -i "s/ <!-- page title -->/${TITLE}/g" $CREATED_FILE_PATH
gsed -i "/<!-- toHomeLinkPath -->/i ${LINK_TAG}" "../src/component/home.html"
```

ターミナルでcmディレクトリ配下に移動して以下の様にコマンドを実行します。

```
sh makePage.sh　 <ディレクトリ> <ディレクトリ> <ディレクトリ> <ファイル名> <タイトル>
```
ディレクトリは左からネストしていく構造となります。

以下を実行してみます。

```
sh makePage.sh three threeChild new 新規で作ったページ
```

![7a67aff65e77e28631d35fa744a791e4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/4078957a-94bd-d291-781b-5db23abd56a6.gif)

以下の様な構造となりました。

```
.
├── cm
│   ├── makePage.sh
│   └── temp.html
└── src
    └── component
        ├── home.html
        ├── one
        │   └── two
        │       ├── first.html
        │       └── second.html
        └── three
            └── threeChild
                └── new.html (新規で作成したページ)
```

### shファイルの簡単な解説

```makePage.sh
#!/bin/sh

CREATED_FILE_PATH="../src/component" #作成予定ファイルのベースのパス
DYNAMIC_DIR_PATH="${CREATED_FILE_PATH}" #コマンドの引数によって動的に作成されるパス

#1
for VAR in "${@:1:($#-2)}" ;
  do
    DYNAMIC_DIR_PATH="${DYNAMIC_DIR_PATH}/${VAR}"
    TO_PAGE_LINK="${TO_PAGE_LINK}/${VAR}" #作成ページへのリンクを作成します。
    mkdir $DYNAMIC_DIR_PATH  #ディレクトリを作成します。すでに存在する場合は作成されません。
    TO_HOME_LINK="..\/${TO_HOME_LINK}" #作成ページからホームページへのリンクを作成します。
  done

FILE_NAME="${@:($#-1):1}.html" #最後から２番目の引数でファイル名を作成
TITLE="${@:($#):1}" #最後の引数でタイトルを作成

TO_PAGE_LINK=".${TO_PAGE_LINK}/${FILE_NAME}"

CREATED_FILE_PATH="${DYNAMIC_DIR_PATH}/${FILE_NAME}"

TO_HOME_LINK="${TO_HOME_LINK}home.html"

cp "./temp.html" $CREATED_FILE_PATH #テンプレートをコピーします。

LINK_TAG="<div> <a href=\"${TO_PAGE_LINK}\">${TITLE}<\/a><\/div>" #作成ページリンク用のaタグを作成します。

#2
gsed -i "s/toHomeLinkPath/${TO_HOME_LINK}/g" $CREATED_FILE_PATH
gsed -i "s/ <!-- page title -->/${TITLE}/g" $CREATED_FILE_PATH
gsed -i "/<!-- toHomeLinkPath -->/i ${LINK_TAG}" "../src/component/home.html"
```

### #1
```
${@} => コマンドの引数を配列で取得できる。

${@:スタートのインデックス:取得個数} => 配列の要素を指定して取得できる。(最初の引数のインデックスは0ではなく1)
例えば ${@:1:3} の場合は 1つ目の引数から3つ取得

$# => 引数の数を取得

つまり以下の場合
for VAR in "${@:1:($#-2)}" 
引数の1つ目から、最後から3番目までの引数を取得します。(引数のうち、ディレクトリをループで回す。)
```

### #2
macの場合、sedコマンドをそのまま実行するとエラーとなるため、GNUのsedをインストールします

```
brew install gnu-sed
```

```
文字列を置換する場合
gsed -i "s/<置換前の文字>/<置換後の文字>/g" 対象のファイル
-i オプションで指定のファイルを上書きしています。

文字列を指定の文字列の直前に挿入する場合。
gsed -i "s/<置換前の文字>/<置換後の文字>/g" <対象のファイル>
gsed -i "/<指定の文字列>/i <挿入したい文字列>" <対象のファイル>
```

### リファクタリング

pipelineを用いてワンライナーで記載。

```
cp "./temp.html" $CREATED_FILE_PATH #テンプレートをコピーします。

LINK_TAG="<div> <a href=\"${TO_PAGE_LINK}\">${TITLE}<\/a><\/div>" #作成ページリンク用のaタグを作成します。

gsed -i "s/toHomeLinkPath/${TO_HOME_LINK}/g" $CREATED_FILE_PATH
gsed -i "s/ <!-- page title -->/${TITLE}/g" $CREATED_FILE_PATH
gsed -i "/<!-- toHomeLinkPath -->/i ${LINK_TAG}" "../src/component/home.html"
```
⬇️
```
LINK_TAG="<div> <a href=\"${TO_PAGE_LINK}\">${TITLE}<\/a><\/div>"

cat "./temp.html" | gsed "s/toHomeLinkPath/${TO_HOME_LINK}/g" | gsed "s/ <!-- page title -->/${TITLE}/g" >$CREATED_FILE_PATH
gsed -i "/<!-- toHomeLinkPath -->/i ${LINK_TAG}" "../src/component/home.html"
```

以上となります。