1.はじめに
筆者がこれまでの開発現場で通常のシェルに触れたことはあるが、次回の配属先でCシェルに初めて触れるため執筆したものになります。そのため覚書レベルとして執筆した記事となります。同様の状況の方には是非読んでもらえればと思います。
実行環境
今回の記事は以下の環境を想定しています。
- OS:Linux(Ubuntu 22.04 LTS)
- csh:
tcsh 6.21.00
(cshの代わりにtcshが利用されるケースが多いです)
Cシェルとは
CシェルはUnix環境で動作するシェルであり、C言語の構文に似ているため、その名が付けられました。
開発された背景として、Unix系のシステムはほとんどC言語で書かれているため、一貫性を保つために設計されたコマンド言語です。
sh,bashとの違い
本記事ではCシェルを紹介しますが、多くの現場で使われているのはsh,bashといったイメージが個人的にはあります。
これらのシェルはsh(Bourne shell)の頭文字を取り、Bシェル系と呼ばれています。
■Bシェル系(Bourne系シェル)
特徴:Bourne shellを基に開発された
種類:sh、bash、zsh...etc
■Cシェル系
特徴:構文がC言語に似ている
種類:csh,tcsh...etc
2.基本構文
ここからはプログラム内でよく使われる基本構文をcshとshで比較してみます。
変数の取扱
・Cシェル :変数はsetコマンドで設定
・sh(Bash):変数は=で設定
変数の参照は、どちらのシェルでも $ (ダラー)を使います。
# Cシェルの場合
set var = "Hello"
echo $var
# shの場合
var="Hello"
echo $var
if文
〈Cシェル〉
# Cシェルの場合
if ($var == 1) then
echo "Hello csh"
endif
〈シェル〉
# shの場合
if [ "$var" -eq 1 ]; then
echo "Hello sh"
fi
異なる点としては以下の3点です。
・条件括弧(() ⇔ [])
・比較演算子
・if文(endif ⇔ fi)
以下は、cshとshで使用する比較演算子の違いです。
| 種類 | 説明 | csh | sh |
|---|---|---|---|
| 等価 | AとBが等しければ true | A == B | A -eq B |
| 不等価 | AとBが等しくなければ true | A != B | A -ne B |
| 大なり | AがBより大なら true | A > B | A -gt B |
| 大なり等価 | AがB以上なら true | A >= B | A -ge B |
| 小なり | AがBより小なら true | A < B | A -lt B |
| 小なり等価 | AがB以下なら true | A <= B | A -le B |
cshではC言語と同一の表現となっています。
3.業務を想定したコマンド
リダイレクト
リダイレクトはシェル上の処理で標準出力や標準エラー出力〈正常終了/異常終了〉の結果を他のファイルに転送する事を指します。通常ならコンソール(画面)上に出力されますが、処理結果・時間・エラー内容をログファイルに残したいときに使用されます。
Cシェルでは、リダイレクトの書き方がBシェル系と異なるため、初心者にとっては混乱することがあります。ここでも両者の違いを押さえておきましょう。
まず、Cシェルで標準出力をリダイレクトする場合の書き方は以下の通りです。
# 標準出力の結果をlog.txtファイルに上書き
# (ファイルが存在すれば丸ごと上書きし、存在しなければ新規作成)
cmd > log.txt
# 標準出力の結果をlog.txtファイルに追加
# (ファイルの最後部に追加し、存在しなければ新規作成)
cmd >> log.txt
cshとshの比較表は以下の通りとなります。
| csh | sh | 出力種類 | 動作 |
|---|---|---|---|
| cmd > log.txt ※ | cmd > log.txt | 標準 | log.txtに上書き |
| cmd >> log.txt | cmd >> log.txt | 標準 | log.txtに追記 |
| - | cmd 2> log.txt | 標準エラー | log.txtに上書き |
| - | cmd 2>> log.txt | 標準エラー | log.txtに追記 |
| cmd >& log.txt | cmd > log.txt 2>&1 | 標準・標準エラー | ともにlog.txtに上書き |
| (cmd > file1) >& file2 | cmd > log.txt 2>&1 | 標準・標準エラー | 標準⇒log、標準エラー⇒log2に上書き |
表を見てわかる通り、cshには標準エラー出力のみを行う機能は存在していません。エラー出力のみを出力するコマンドは工夫することで実現可能ですが、実務上でもエラー出力のみを行う頻度も高くなさそうなため、ここでは省略しています。
※cmd > log.txtでlog.txtが存在する場合、file: File exists というエラーが表示されることがあります。この原因は、Cシェルにおける noclobber というオプションが有効になっているためです。
〈重要度が高いファイルを誤って上書きしないためのオプションです。〉
# リダイレクト時、既存ファイルの上書きをしない
set noclobber
# 上述のオプションを解除
unset noclobber
以下はリダイレクトを使ってバックアップ処理のログを残す簡単なスクリプト例です。
if ($status == 0)のstatusに付いてですが、これはcshの場合、直前のコマンドの終了ステータスを参照できるものです。正常終了であれば0が返されるためこのような書き方となっています。
#!/bin/csh
# スクリプト:backup_script.csh
# バックアップ処理開始
echo "バックアップ開始 `date`" > backup.log
# 実際のバックアップコマンド(仮)
tar czf ~/backup/daily_backup.tar.gz ~/data >& backup_error.log
# tarコマンドの終了ステータスを確認
if ($status == 0) then
echo "バックアップ成功 `date`" >> backup.log
else
echo "バックアップ失敗 `date`" >> backup.log
endif
以下はバックアップ成功時と失敗時の出力結果です。
バックアップ成功時
バックアップ開始
バックアップ成功
tar: Removing leading `/' from member names
バックアップ失敗時
バックアップ開始
バックアップ失敗
tar: /data: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
4.終わりに
今回はcshのコマンドを解説しました。Bシェル系しか触れてない人で、これからCシェルを扱う人の参考になれば幸いです。