[精讚] [會員登入]
1

[BASH] 自建檔案拷背程式--把指定的檔案拷背到指定的位置。

Git 是很好用的版本控制程式,但我沒辦法使用。 原因就是資安。用SHELL自建簡易的GIT

分享此文連結 //n.sfs.tw/16531

分享連結 [BASH] 自建檔案拷背程式--把指定的檔案拷背到指定的位置。@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2025-07-09 03:21:14 最後編修
2025-07-09 02:23:53 By 張○○
 

自動目錄

<此文是札記方式寫的文章,如果想直接用程式請滑到最下面>

Git 是很好用的版本控制程式,但我沒辦法使用。

原因就是資安。anyway,我遇到棘手的問題:

A機是我的測試和開發機,我在測試機寫好的程式,要經過很複雜的程序搬到B機的臨時目錄上,再到B機上一個個copy到指定的位置。
如果要這樣做,我有兩個方法處理,一個就是把 A機的所有目錄檔案壓縮搬到B 機,另一個方式就是把異動過的檔案取出來,再手動一個個搬。

事實上,因為是分散效能的關係,我要操作同樣的動作到 CDE機上,不但有可能遺漏,還有可能搬錯,而且很費精神。

所以我想一個方法

[在A機中]
步1  如果我的一個檔案異動清單 diff.txt,寫一個 SHELL 讓清單中的檔案從來源目錄 ./srcwww/ 拷背到目的目錄 ./modwww/ 中指定的位置
步2  我再將這個 ./modwww/ 目錄打包連同 diff.txt 搬移到 B機的臨時目錄中。

[在B機中]
步3 解包並執行 SHELL 讓異動的檔案搬到正式的目錄 ./targwww/ 中

完美~~附帶功能:

- 目的路徑中若資料夾不存在,就自動建立
- 如果檔案不存在,會顯示警告但不會中止
- 如果目標檔案在 ./targwww/ 已經存在,會自動備份到 ./backup/ 目錄(也保留原始路徑結構)
- diff.txt 不存在就停止

程式碼 copy_diff_to_www.sh 初版

#!/bin/bash

# 設定來源根目錄與檔案清單、目標根目錄
source_root="./html"
diff_file="diff.txt"
target_root="/home/axer/web"
backup_root="./backup"

if [ ! -f diff.txt ]; then
  echo "檔案 diff.txt 不存在,停止執行。"
  echo "你可以下指令來產生這個檔 git diff --name-only <logid> HEAD > diff.txt"
  exit 1
fi


# 一行一行處理 diff.txt
while IFS= read -r filepath; do
  # 組合完整路徑
  src_file="$source_root/$filepath"
  target_file="$target_root/$filepath"
  backup_file="$backup_root/$filepath"
  target_dir="$(dirname "$target_file")"
  backup_dir="$(dirname "$backup_file")"

  # 檢查來源檔案是否存在
  if [ -f "$src_file" ]; then
    # 若目標檔案已存在,先備份
    if [ -f "$target_file" ]; then
      mkdir -p "$backup_dir"
      cp "$target_file" "$backup_file"
      echo "???? 已備份舊檔:$target_file → $backup_file"
    fi

    # 建立目標資料夾
    mkdir -p "$target_dir"
    cp "$src_file" "$target_file"
    echo "✔ 拷貝 $src_file → $target_file"
  else
    echo "⚠ 檔案不存在:$src_file"
  fi
done < "$diff_file"

$ chmod 711 copy_diff_to_www.sh

然後和 diff.txt 放在同一個目錄下即可。

 

產生差異檔案 diff.txt 並執行

重點來了要怎麼產生?一個個打嗎?別擔心,在測試機上可以使用 git。

diff.txt 的產生方法
# git diff --name-only <commit id> HEAD > diff.txt

或是只取回 ACM三種狀態的檔案進行複製。

A:新增 (Added)
C:複製 (Copied)
M:修改 (Modified)
D:刪除 (Deleted)

# git diff --name-only  --diff-filter=ACM <commit id> HEAD > diff.txt 

這樣會產生從commit id到現在所有非刪除異動的檔案

指令範例

# git diff --name-only f0bc55e7ab53e0523581526e52c541c23fc48332 HEAD > diff.txt

diff.txt 內容範例如下

note/appusers/getstat.php
book/comic/reading.php
noval/appusers/moving_export.php
book/roles/notice.php
theme/img/pic_login.jpg
...清單略...

修改目錄的參數後執行即可

# 設定來源根目錄與檔案清單、目標根目錄
source_root="./srcwww"
diff_file="diff.txt"
target_root="./tagwww"

目錄是相對於此 shell 所在的位置,你也可以用絕對位置

執行
./copy_diff_to_www.sh

▒▒▒▒▒▒▒▒    重新思考的分隔線  ▒▒▒▒▒▒▒▒▒▒▒▒

那刪除呢?是不是目的有這個檔也要把他刪除,這樣打包時就不會帶上他。

另外,只要目的原本有舊的檔案,無論是異動或是刪除,都要先備份,備份不應全部丟在一個目錄壓來壓去,應該以日期作為區隔。

所以程式特色改成這樣:

- 目的路徑中若資料夾不存在,就自動建立
- 如果檔案不存在,會顯示警告但不會中止
- 如果目標檔案在 ./targwww/ 已經存在,會自動備份到 ./backup/ 目錄(也保留原始路徑結構)
- diff.txt 不存在就停止
- 考慮檔案的異動狀態

 

程式碼 copy_diff_to_www.sh 終版

#!/bin/bash

# 設定來源與目標根目錄
source_root="/newwww"
target_root="./www"

# 取得當前日期,用於備份子資料夾
today=$(date +%F)  # 格式:2025-07-03
backup_root="./backup/$today"

diff_file="diff.txt"

# 檢查清單檔是否存在
if [ ! -f "$diff_file" ]; then
  echo "❌ 檔案 $diff_file 不存在,停止執行"
  exit 1
fi

# 處理每一行
while IFS=$'\t' read -r change_type filepath; do
  # 忽略空行
  if [[ -z "$filepath" ]]; then
    continue
  fi

  src_file="$source_root/$filepath"
  target_file="$target_root/$filepath"
  backup_file="$backup_root/$filepath"
  target_dir="$(dirname "$target_file")"
  backup_dir="$(dirname "$backup_file")"

  case "$change_type" in
    A|M|C)
      # 來源檔案存在才處理
      if [ -f "$src_file" ]; then
        # 若目標檔案存在,先備份
        if [ -f "$target_file" ]; then
          mkdir -p "$backup_dir"
          cp "$target_file" "$backup_file"
          echo "???? 已備份舊檔:$target_file → $backup_file"
        fi
        # 建立目標資料夾並拷貝
        mkdir -p "$target_dir"
        cp "$src_file" "$target_file"
        echo "✔ 拷貝 $src_file → $target_file"
      else
        echo "⚠ 檔案不存在於來源:$src_file"
      fi
      ;;
    D)
      if [ -f "$target_file" ]; then
        mkdir -p "$backup_dir"
        cp "$target_file" "$backup_file"
        rm "$target_file"
        echo "❌ 刪除 $target_file(已備份至 $backup_file)"
      else
        echo "⚠ 刪除項目不存在於目的地:$target_file"
      fi
      ;;
    *)
      echo "❓ 未知變更類型:$change_type $filepath"
      ;;
  esac

done < "$diff_file"

 

產生有異動狀態的 diff.txt

# git diff --name-status  --diff-filter=ACM <commit id> HEAD > diff.txt 

# git diff --name-status f0bc55e7ab53e0523581526e52c541c23fc48332 HEAD > diff.txt

diff.txt 的範例:

其中第一個字元是異動狀態,接著一個 \t ,然後是檔名。

執行結果範例:

所以最後我的方案是:

[在A機中]
步1  產生異動 diff.txt,執行這個 SHELL 產生一個 ./modwww

步2  將這個 ./modwww/ 目錄打包連同 diff.txt 搬移到 B機的臨時目錄中。

  tar -czf modwww.tar.gz ./modwww

[在B機中]
步3 解包並執行 SHELL 讓異動的檔案搬到正式的目錄 ./targwww/ 中

  tar -xzf modwww.tar.gz

 

備份檔目錄

備份加上日期分隔,非常棒:

backup/
└── 2025-07-09
    ├── config
    ├── experiment
    ├── lib
    ├── login.php
    └── theme

有異動的才會出現,方便還原。

 

結論

感謝 AI,讚嘆AI

程式都是 CHATGPT 寫的,我是個廢物。

 

 

END

你可能感興趣的文章

Centos7 安裝 docker-composer 及使用 docker compose 是使用docker的利器,可以讓很多的指令用文檔的方式載入。

[Centos] 安裝及使用postfix,設定虛擬帳號及轉寄 使用postfix來設定虛擬帳號及轉寄

使用GPG檔案加解密 簡易的檔案加解密方式,可以讓你重要的資料包括文字檔加解密。

[Centos8] 校時ntpdate? 以前常用的ntpdate,在centos8竟然不見了?

[Centos8] 安裝phpMyAdmin Centos 8目前只能採用tarball安裝法

[bc] linux 的計算機bc 如何計算帶小數點的指數 用 bc 來計算帶小數點的指數,得轉個彎才行

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

一個邏輯的錯誤刪了全部檔案的經驗 今天本來想做一件很簡單的事,但卻足足浪費我多一倍的時間,再加上刪掉我全部的檔案,原因只是因為我自己的邏輯錯誤。

好用的3+2碼郵遞區號查詢系統推薦 網路上找到用地址輸入判斷3+2碼郵遞區號的辨識率不高,除了這個網站…

詭異的創業思維 創業的思維中,有多少銀彈,有多少技術,有多少人脈,有多少時間等等,每個都要考慮進去,以熱忱建立的關係脆弱的像蘇打餅乾一樣..

[Bootstrap] Datepicker使用/Bootstrap日期選日期選擇器的使用 Bootstrap日期選日期選擇器的使用

讓radio box 或checkbox 好按 在行動裝置下,radio box及checkbox變得很難按得到