0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

csh で作るシンプルなディレクトリ/変更ファイル・バックアップスクリプト

0
Posted at

はじめに

日々の開発やサーバ運用では、「作業前にいったん固めておきたい」「今日触ったファイルだけ残したい」という場面がよくあります。

この記事では、csh で書いたバックアップスクリプト file_backup.csh を紹介します。
tar + gzip を使い、パーミッションを保ったままバックアップできます。

できること

モード オプション 内容
全体バックアップ (なし) 指定ディレクトリ全体を yyyymmddhhmmss_bk.tar.gz に圧縮
変更ファイルバックアップ -c 本日更新されたファイルのみをファイル単位で ./bk に保存
  • 圧縮形式: tar.gz(パーミッション情報を含む)
  • 対象はディレクトリ指定
  • ヘルプ: -h / --help

環境

  • csh / tcsh が使える Unix 系環境
  • tar / gzip / find / date / touch など標準コマンド
chmod +x file_backup.csh

使い方

1. ディレクトリ全体をバックアップ

./file_backup.csh /path/to/target

実行ディレクトリに、次のようなアーカイブができます。

20261001153045_bk.tar.gz

2. 本日更新されたファイルだけバックアップ(-c)

./file_backup.csh -c /path/to/target

実行ディレクトリ配下の bk/ に、ファイル単位の tar.gz が出力されます。

bk/
  target_subdir_foo.txt.tar.gz
  target_another_bar.c.tar.gz
  ...

パスの / は _ に置換してファイル名にしているため、同名ファイルの衝突を避けやすくしています。

3. ヘルプ

./file_backup.csh -h
# または
./file_backup.csh --help

処理の流れ

共通処理

  1. 引数を解析(-c / -h / 対象ディレクトリ)
  2. 対象がディレクトリか確認
  3. 絶対パス・親ディレクトリ名・ベース名を取得

変更ファイルモード(-c)

  1. 作業ディレクトリに bk/ を用意
  2. /tmp に「本日 00:00」の参照ファイルを touch -t で作成
  3. find ... -newer で本日以降に更新された通常ファイルを列挙
  4. 各ファイルを個別に tar czf で圧縮
  5. 成功/失敗件数を表示して終了

ポイントは、「今日 0 時より新しいファイル」 を参照ファイル比較で拾っていることです。

touch -t `date +%Y%m%d0000` "$reffile"
find "$base" -type f -newer "$reffile" -print > "$listfile"

全体バックアップモード

  1. 現在時刻から YYYYMMDDhhmmss を生成
  2. 親ディレクトリへ移動し、対象ディレクトリ名を tar czf で固める
  3. 作業ディレクトリに タイムスタンプ_bk.tar.gz を出力
set stamp = `date +%Y%m%d%H%M%S`
set archpath = "${workdir}/${stamp}_bk.tar.gz"
tar czf "$archpath" "$base"

実行例

全体バックアップ

$ ./file_backup.csh ./mydir
Full backup: /home/user/work/mydir -> /home/user/work/20261001154500_bk.tar.gz
Done: /home/user/work/20261001154500_bk.tar.gz

変更ファイルバックアップ

$ ./file_backup.csh -c ./mydir
Changed-file backup: 2 file(s) -> /home/user/work/bk
  OK  : mydir/a.txt -> mydir_a.txt.tar.gz
  OK  : mydir/src/b.c -> mydir_src_b.c.tar.gz
Done. success=2 fail=0 (output: /home/user/work/bk)

本日更新ファイルが無い場合:

No files modified today under: /home/user/work/mydir

設計上の工夫

  • 相対パスで tar する
    親ディレクトリに cd してから対象名だけを渡すため、アーカイブ内のパスが深くなりすぎません。
  • PID 付き一時ファイル
    /tmp/bk_today_ref.$$ のようにプロセス ID を付け、同時実行時の衝突を低減しています。
  • ファイル単位アーカイブ名の正規化
    パス区切りを _ に置換し、bk/ 配下での上書き衝突を防ぎます。
  • 終了コード
    失敗があれば exit 1 になるので、cron や他スクリプトから呼びやすいです。

注意点

  • 「本日更新」は ローカルタイムの 0 時以降に更新されたファイル が対象です(タイムゾーンに注意)
  • -c の出力先は スクリプト実行時のカレントディレクトリ配下の bk/ です
  • 全体バックアップの出力先も カレントディレクトリ です
  • 巨大ディレクトリでは find や個別 tar に時間がかかることがあります
  • シンボリックリンクや特殊ファイルの扱いは find -type f / tar の仕様に依存します

ソースコード

#!/bin/csh -f
#
# file_backup.csh - ディレクトリ/変更ファイルのバックアップ
#
# 使い方:
#   file_backup.csh [-c] <バックアップ対象ディレクトリ>
#
#   -c   : 本日更新されたファイルのみをファイル単位で圧縮し、作業ディレクトリ/bk に保存
#   (なし): 指定ディレクトリ全体を yyyymmddhhmmss_bk.tar.gz として圧縮
#
# 圧縮: tar + gzip(パーミッション情報を含む)
#

set mode = "full"
set target = ""

while ($#argv > 0)
    switch ($argv[1])
        case -c:
            set mode = "changed"
            shift
            breaksw
        case -h:
        case --help:
            echo "Usage: $0 [-c] <directory>"
            echo "  -c   backup only files modified today (per-file tar.gz under ./bk)"
            echo "  (no option) full directory backup as yyyymmddhhmmss_bk.tar.gz"
            exit 0
            breaksw
        default:
            if ("$target" != "") then
                echo "Error: too many arguments"
                echo "Usage: $0 [-c] <directory>"
                exit 1
            endif
            set target = "$argv[1]"
            shift
            breaksw
    endsw
end

if ("$target" == "") then
    echo "Usage: $0 [-c] <directory>"
    exit 1
endif

if (! -d "$target") then
    echo "Error: '$target' is not a directory"
    exit 1
endif

set workdir = "`pwd`"
set bkdir = "${workdir}/bk"
set saved_pwd = "`pwd`"

cd "$target"
set abs_target = "`pwd`"
cd "$saved_pwd"

set parent = `dirname "$abs_target"`
set base = `basename "$abs_target"`

# 変更ファイルバックアップ (-c)
if ("$mode" == "changed") then
    if (! -d "$bkdir") then
        mkdir -p "$bkdir"
        if ($status != 0) then
            echo "Error: cannot create bk directory: $bkdir"
            exit 1
        endif
    endif

    set reffile = "/tmp/bk_today_ref.$$"
    set listfile = "/tmp/bk_file_list.$$"
    touch -t `date +%Y%m%d0000` "$reffile"
    if ($status != 0) then
        echo "Error: cannot create today reference file"
        exit 1
    endif

    cd "$parent"
    find "$base" -type f -newer "$reffile" -print > "$listfile"
    set file_count = `wc -l < "$listfile" | tr -d ' '`

    if ($file_count == 0) then
        echo "No files modified today under: $abs_target"
        cd "$workdir"
        rm -f "$reffile" "$listfile"
        exit 0
    endif

    echo "Changed-file backup: $file_count file(s) -> $bkdir"
    set i = 1
    set ok = 0
    set fail = 0

    while ($i <= $file_count)
        set f = "`sed -n ${i}p $listfile`"
        if ("$f" != "") then
            set archname = `echo "$f" | sed 's/\//_/g'`
            set archpath = "${bkdir}/${archname}.tar.gz"
            tar czf "$archpath" "$f"
            if ($status == 0) then
                echo "  OK  : $f -> ${archname}.tar.gz"
                @ ok++
            else
                echo "  FAIL: $f"
                @ fail++
            endif
        endif
        @ i++
    end

    cd "$workdir"
    rm -f "$reffile" "$listfile"

    echo "Done. success=$ok fail=$fail (output: $bkdir)"
    if ($fail != 0) then
        exit 1
    endif
    exit 0
endif

# 全体バックアップ
set stamp = `date +%Y%m%d%H%M%S`
set archpath = "${workdir}/${stamp}_bk.tar.gz"

echo "Full backup: $abs_target -> $archpath"
cd "$parent"
tar czf "$archpath" "$base"
set tar_status = $status
cd "$workdir"

if ($tar_status == 0) then
    echo "Done: $archpath"
    exit 0
else
    echo "Error: full backup failed"
    exit 1
endif

まとめ

  • オプションなしで ディレクトリ全体バックアップ
  • -c で 本日更新ファイルのみをファイル単位バックアップ
  • tar.gz でパーミッション付き保存
  • csh でも十分実用的なバックアップツールにできます

「作業前の保険」「今日の差分だけ残す」といった用途に、ぜひ使ってみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?