macOS 系統自帶的 screencapture 命令提供了基本的螢幕截圖功能,但缺乏自動化和批次處理能力。為此,本文介紹一個名為 screencapture2 的 Bash 指令碼,它可以自動捕捉螢幕畫面,並可選擇生成 GIF 動畫。指令碼支援自定義截圖頻率、最大截圖數量等引數,並使用 ImageMagick 的 convert 命令將多張截圖合併成 GIF 動畫。此外,文章也探討瞭如何利用 screencapture 命令結合其他工具實作進階螢幕監控,例如僅在螢幕內容發生變化時才進行截圖,以節省儲存空間。文章還提供了一些實用的 macOS 指令碼範例,例如動態更新終端機標題,以及匯出 iTunes 音樂函式庫清單等,方便使用者管理系統和個人資料。

自動化螢幕截圖:screencapture2 指令碼詳解

在 macOS 系統中,內建了一個非常實用的螢幕截圖功能,可以透過按下鍵盤上的 Shift + Command + 3Shift + Command + 4 來使用。不過,除了這個基本的用法之外,macOS 還提供了一個名為 screencapture 的命令列工具,讓使用者能夠更靈活地進行螢幕截圖的操作。

screencapture 命令介紹

screencapture 是一個功能強大的命令列工具,可以用來捕捉螢幕畫面並儲存為圖片檔案。透過輸入 screencapture -h,可以檢視其基本的使用方法與引數選項。

$ screencapture -h
screencapture: illegal option -- h
usage: screencapture [-icMPmwsWxSCUtoa] [files]
-c         強制將螢幕截圖儲存到剪貼簿
-C         同時捕捉遊標和螢幕畫面(僅在非互動模式下有效)
-d         以圖形方式顯示錯誤訊息
-i         互動式螢幕截圖,可選擇區域或視窗
-m         只捕捉主螢幕畫面(如果未指定 -i 引數)
-M         將螢幕截圖輸出到新的郵件訊息中
-o         在視窗捕捉模式下,不包含視窗陰影
-P         將螢幕截圖輸出開啟在 Preview 應用程式中
-s         只允許滑鼠選擇模式
-S         在視窗捕捉模式下,捕捉整個螢幕而非單一視窗
-t<格式>   指定輸出圖片的格式(預設為 png,其他選項包括 pdf、jpg、tiff 等)
-T<秒數>   在指定的秒數後進行螢幕截圖(預設為 5 秒)

自動化螢幕截圖指令碼:screencapture2

為了讓 screencapture 的功能更為強大,我們可以撰寫一個名為 screencapture2 的 Bash 指令碼,來自動化地進行一系列的螢幕截圖,並將結果儲存為多個圖片檔案。

指令碼程式碼

#!/bin/bash
# screencapture2 - 自動化使用 macOS 的 screencapture 命令來捕捉一系列螢幕截圖

capture="$(which screencapture) -x -m -C"
freq=60  # 每 60 秒進行一次螢幕截圖
maxshots=30  # 最多進行 30 次螢幕截圖
animate=0  # 是否產生動畫 GIF(預設為否)

while getopts "af:m" opt; do
  case $opt in
    a) animate=1 ;;
    f) freq=$OPTARG ;;
    m) maxshots=$OPTARG ;;
    ?) echo "用法:$0 [-a] [-f 頻率] [-m 最大截圖數]" >&2; exit 1 ;;
  esac
done

counter=0
while [ $counter -lt $maxshots ]; do
  $capture capture${counter}.jpg
  counter=$((counter + 1))
  sleep $freq
done

if [ $animate -eq 1 ]; then
  convert -delay 100 -loop 0 -resize "33%" capture* animated-captures.gif
fi

exit 0

#### 內容解密:

  1. capture="$(which screencapture) -x -m -C":這行指令用來定義 capture 變數,內容是 screencapture 命令的完整路徑,並且帶有 -x(不播放聲音)、-m(只捕捉主螢幕)和 -C(捕捉遊標)等引數。
  2. while getopts "af:m" opt; do:這是一個用來處理命令列引數的迴圈,可以根據使用者輸入的選項(如 -a-f-m)來調整指令碼的行為。
  3. $capture capture${counter}.jpg:這行指令實際執行螢幕截圖,並將結果儲存為 capture0.jpgcapture1.jpg 等檔案。
  4. convert -delay 100 -loop 0 -resize "33%" capture* animated-captures.gif:如果使用者指定了 -a 引數,指令碼會使用 ImageMagick 的 convert 命令,將所有截圖圖片合併成一個動畫 GIF 檔案。

使用方法與結果

要執行這個指令碼,可以簡單地輸入 ./screencapture2 &。如果需要指定截圖頻率或最大截圖數,可以使用如下的指令:

$ ./screencapture2 -f 5 -m 30 &

執行結果會在當前目錄下產生一系列的 JPEG 檔案(如 capture0.jpgcapture1.jpg 等),以及一個名為 animated-captures.gif 的動畫 GIF 檔案(如果指定了 -a 引數)。

$ ls -s *gif *jpg
4448 animated-captures.gif 4216 capture2.jpg 25728 capture5.jpg
4304 capture0.jpg 4680 capture3.jpg 4456 capture6.jpg
4296 capture1.jpg 4680 capture4.jpg

這個指令碼非常適合用於需要自動記錄螢幕畫面的場合,例如製作教學影片或監控電腦使用情況等。透過調整引數和使用 ImageMagick 的 convert 命令,我們可以靈活地控制截圖的頻率、數量和輸出格式,甚至產生動畫 GIF 以便快速預覽結果。

強化 macOS 實用指令碼功能

在 macOS 環境下,透過自訂的指令碼可以大幅提升工作效率與系統管理的便利性。本章節將探討三個實用的指令碼,分別是螢幕監控工具、動態調整終端機標題以及匯出 iTunes 音樂函式庫清單。

1. 進階螢幕監控工具的改良

對於需要長期監控螢幕內容的情境,簡單地持續截圖會浪費大量硬碟空間。一個更聰明的做法是隻在螢幕內容發生變化時才進行截圖。雖然市面上有第三方工具可以實作這一功能,但我們可以透過自訂指令碼來控制截圖的時機與頻率。

程式碼解析

以下是一個簡化的邏輯範例,用於檢查螢幕是否發生變化:

#!/bin/bash
# screen_monitor.sh

# 初始化變數
previous_image=$(mktemp)
current_image=$(mktemp)

# 首次截圖
screencapture "$previous_image"

while true; do
    screencapture "$current_image"
    if ! cmp -s "$previous_image" "$current_image"; then
        # 螢幕內容有變化,處理新截圖
        echo "螢幕內容已變更"
        cp "$current_image" "${current_image}_changed_$(date +%s).png"
        cp "$current_image" "$previous_image"
    fi
    sleep 1 # 每秒檢查一次
done

#### 內容解密:

  1. mktemp 命令:用於建立暫存檔案,以儲存截圖。
  2. screencapture 命令:macOS 下用於螢幕截圖的命令列工具。
  3. cmp -s 命令:比較兩個檔案是否相同,若不同則表示螢幕內容已變更。
  4. sleep 1:設定檢查間隔為一秒,可根據需求調整。

2. 動態設定終端機標題

在 macOS 的終端機(Terminal)中,可以透過特殊的轉義序列動態更改視窗標題。以下是一個簡單的指令碼,用於將當前工作目錄顯示在終端機標題上。

程式碼解析

#!/bin/bash
# titleterm.sh

if [ $# -eq 0 ]; then
    echo "用法: $0 標題" >&2
    exit 1
else
    echo -e "\033]0;$@\007"
fi
exit 0

#### 內容解密:

  1. echo -e "\033]0;$@\007":輸出 ANSI 轉義序列,將終端機標題設為引數 $@ 的內容。
  2. $# -eq 0:檢查是否有輸入引數,若無則輸出用法並離開。

若要讓終端機標題自動顯示目前工作目錄,可以在 .bash_profile 中加入以下設定:

export PROMPT_COMMAND="titleterm \"\$PWD\""

3. 匯出 iTunes 音樂函式庫清單

對於長期使用 iTunes 的使用者來說,音樂函式庫的管理與匯出是一項實用功能。以下指令碼可提取 iTunes 音樂函式庫的目錄結構,並以簡潔的方式輸出。

程式碼解析

#!/bin/bash
# ituneslist.sh

itunehome="$HOME/Music/iTunes"
ituneconfig="$itunehome/iTunes Music Library.xml"
musiclib="/$(grep '>Music Folder<' "$ituneconfig" | cut -d/ -f5- | cut -d\< -f1 | sed 's/%20/ /g')"

echo "您的音樂函式庫位於: $musiclib"

if [ ! -d "$musiclib" ]; then
    echo "$0: 錯誤: 音樂函式庫 $musiclib 不是一個目錄?" >&2
    exit 1
fi

find "$musiclib" -type d -mindepth 2 -maxdepth 2 \! -name '.*' -print | sed "s|$musiclib/||"

#### 內容解密:

  1. grepcut 命令組合:從 iTunes 設定檔中提取音樂函式庫的實際路徑。
  2. sed 's/%20/ /g':將 URL 編碼中的 %20 替換為空格,以正確顯示路徑。
  3. find 命令:列出音樂函式庫中的目錄結構,限制層級以避免過多的輸出。
  4. sed "s|$musiclib/||":移除輸出中的音樂函式庫根目錄,使結果更簡潔。

強化版 OS X 指令碼實戰與遊戲開發

最佳化 iTunes 清單指令碼

在 macOS 環境中,自動化管理 iTunes 媒體函式庫是一項常見需求。透過自訂指令碼,可以實作對音樂、電影等媒體檔案的精細控制。

關鍵技術解析

  1. iTunes 媒體函式庫路徑擷取

    • 指令碼首先讀取 iTunes 設定檔中的媒體函式庫路徑。
    • 透過解析 XML 檔案,取得媒體函式庫的實際儲存位置。
  2. 輸出結果處理

    • 當處理大型音樂收藏時,輸出結果可能非常龐大。
    • 可使用命令如 head 來擷取輸出結果的前幾行進行檢視。
    $ ituneslist | head -15
    
  3. 擴充套件應用場景

    • 將 iTunes 媒體函式庫目錄設定為網路可存取路徑,並在 XML 檔案中指定該路徑作為音樂資料夾。
    • 此舉可實作跨裝置存取媒體函式庫。

改良 open 命令的實用性

macOS 中的 open 命令用於開啟檔案或應用程式,但其使用方式存在一定限制。透過建立包裝指令碼 open2,可以提升其易用性。

程式碼解析

#!/bin/bash
# open2--智慧包裝 OS X 'open' 命令以提升其實用性

# 首先嘗試直接使用提供的引數
if ! open "$@" >/dev/null 2>&1; then
    if ! open -a "$@" >/dev/null 2>&1; then
        # 若有多個引數則離開
        if [ $# -gt 1 ]; then
            echo "open: 不支援多個程式" >&2
            exit 1
        else
            # 使用 case 陳述式匹配常見應用程式暱稱
            case $(echo $1 | tr '[:upper:]' '[:lower:]') in
                activ*|cpu ) app="Activity Monitor" ;;
                addr* ) app="Address Book" ;;
                chat ) app="Messages" ;;
                dvd ) app="DVD Player" ;;
                excel ) app="Microsoft Excel" ;;
                info* ) app="System Information" ;;
                prefs ) app="System Preferences" ;;
                qt|quicktime ) app="QuickTime Player" ;;
                word ) app="Microsoft Word" ;;
                * ) echo "open: 無法處理 $1" >&2
                    exit 1
            esac
            echo "您輸入的是 $1,但我認為您指的是 $app。" >&2
            open -a "$app"
        fi
    fi
fi
exit 0

#### 內容解密:

  1. 錯誤處理機制

    • 指令碼首先嘗試直接使用 open 命令開啟指定的檔案或應用程式。
    • 若失敗,則檢查是否為有效的應用程式名稱。
  2. 暱稱匹配功能

    • 透過 case 陳述式實作對常見應用程式暱稱的匹配。
    • 例如,輸入 “excel” 時會自動開啟 “Microsoft Excel”。
  3. 多引數處理

    • 當輸入多個引數時,指令碼會輸出錯誤訊息並離開。

使用 Shell 指令碼開發遊戲

Shell 指令碼不僅可用於系統管理,還可用於開發有趣的遊戲。

簡易範例:rot13 編碼與解碼

$ echo "兩個男人走進酒吧..." | tr '[a-zA-Z]' '[n-za-mN-ZA-M]'

輸出:

NFR gjb rkcyr jnyx vagb n one...

再次套用相同的轉換即可解碼:

$ echo 'NFR gjb rkcyr jnyx vagb n one...' | tr '[a-zA-Z]' '[n-za-mN-ZA-M]'

輸出:

兩個男人走進酒吧...

迴文檢查器

testit="$(echo $@ | sed 's/[^[:alpha:]]//g' | tr '[:upper:]' '[:lower:]')"
backward="$(echo $testit | rev)"
if [ "$testit" = "$backward" ]; then
    echo "$@ 是迴文"
else
    echo "$@ 不是迴文"
fi

解謎遊戲:單詞重組

這是一個基本的單詞重組遊戲,玩家需要猜測原始單詞。

程式碼解析

#!/bin/bash
# unscramble--隨機選取單詞並打亂順序,要求玩家猜測原始單詞

wordlib="/usr/lib/games/long-words.txt"

scrambleword() {
    # 從 wordlib 中隨機選取單詞並打亂順序
    match="$(randomquote $wordlib)"
    len=${#match}
    scrambled=""; lastval=1
    
    for ((val=1; val < len; )); do
        if [ $(($RANDOM % 2)) -eq 1 ]; then
            scrambled=$scrambled$(echo $match | cut -c$val)
        else
            scrambled=$(echo $match | cut -c$val)$scrambled
        fi
        val=$((val + 1))
    done
}

if [ ! -r $wordlib ]; then
    echo "$0: 缺少單詞函式庫 $wordlib" >&2
    exit 1
fi

until [ "$guess" = "quit" ]; do
    scrambleword
    # ... (遊戲邏輯)
done

#### 內容解密:

  1. 單詞函式庫檢查

    • 指令碼首先檢查單詞函式庫檔案是否存在且可讀。
  2. 單詞打亂邏輯

    • 使用迴圈逐一處理單詞字元,並隨機決定其在新字串中的位置。
  3. 遊戲迴圈

    • 不斷重複選取新單詞並打亂順序,直到玩家輸入 “quit”。