若要在現有的 Mac 文字檔特定行插入文字,請使用「捷徑」的 Shell 動作建立編輯後的副本、檢查內容,再於 Finder 中重新命名。本指南使用一次性範例,在第 3 行之前插入一行。

這裡要做的是在小型本機純文字檔中新增一行,同時維持周圍各行的順序。你將建立一個 Finder 捷徑,且只接受一個檔案。插入文字和行號都寫在指令碼中,因此可輕鬆在一次性副本上重複相同編輯。

「在第 3 行插入」是什麼意思?

本文所說的插入,是將新文字放在現有編號行的前面。原本有三行時,在第 3 行前插入 Birch 會產生四行:

位置 原始檔案 編輯後的檔案
1 Cedar Cedar
2 Maple Maple
3 Willow Birch
4 — Willow

一行是以換行符號分隔的記錄,不是編輯器因視覺換行而顯示的列。空白行也會計算在內。本範例使用一般 UTF-8 純文字、LF 行尾,且最後一行後有換行符號。本次操作請維持這些條件;富文字文件以及使用其他編碼或行尾的檔案,需要採取不同的處理方式。

執行編輯的指令是 macOS 的 sed。其數字位址從 1 開始計算行數,而 i 指令會在指定行之前寫入插入文字。它通常會將轉換後的內容寫到標準輸出。這些文件記載的行為讓捷徑能建立獨立的結果檔案。Apple 發行的 sed 手冊

建立一次性文字檔

開啟「終端機」,貼上以下完整設定區塊。它會在桌面建立名為 Line Insert Demo 的資料夾,以及名為 notes.txt 的三行檔案。如果該資料夾名稱已存在,設定程序就會停止;請先選擇新的資料夾名稱再重試。

/bin/sh <<'SH'
set -e
demo_dir="$HOME/Desktop/Line Insert Demo"
/bin/mkdir "$demo_dir"
printf '%s\n' 'Cedar' 'Maple' 'Willow' > "$demo_dir/notes.txt"
printf 'Created: %s\n' "$demo_dir/notes.txt"
SH

建立資料夾時刻意省略了允許使用既有目錄的選項。只有在建立新資料夾後才會執行寫入檔案的步驟,因此這項設定不會覆寫先前的範例。Apple 的 Shell 文件說明如何使用 printf 和輸出重新導向來建立文字檔。Shell 輸入與輸出

請在這個一次性資料夾中完成本次練習。在 Finder 中開啟桌面並找到 Line Insert Demo;建立捷徑後,你會選取其中的 notes.txt 檔案。

建立輸入類型正確的 Finder 捷徑

在「捷徑」中建立一個名為 Insert Birch Before Line 3 的捷徑。Apple 說明了如何使用工具列的「新增」按鈕建立捷徑、為其命名,以及從側邊欄新增動作。在 Mac 上建立自訂捷徑

請依照以下方式設定:

  1. 開啟捷徑的 Details,啟用 Use as Quick Action,並選取 Finder。
  2. 在捷徑的輸入標題中,將接受的內容改為 Files,並關閉其他類型。
  3. 新增 Run Shell Script 動作。
  4. 將其 Shell 設為 /bin/sh、Input 設為 Shortcut Input,並將 Pass Input 設為 as arguments。
  5. 將動作範例指令碼換成下一節的完整程式。

Apple 說明了如何啟用 Finder 捷徑,以及如何限制捷徑接受的輸入類型。其 Files 類型包含許多種類的文件,因此此設定會讓捷徑能接收檔案,但不會驗證檔案的文字格式。指令碼會另外進行更嚴格的檢查。在 Mac 上工作時執行捷徑、限制捷徑的輸入、瞭解輸入類型

輸入流程很重要:Finder 將檔案交給「捷徑」,而 Shell 動作會將檔案路徑當成引數傳遞,在指令碼中可透過 $1 取得。請勿在 Shell 動作之前加入讀取文字的動作:此程式需要檔案路徑,才能讀取現有檔案並選擇相鄰的輸出檔名。

Apple 確認「捷徑」for Mac 支援直接在編輯器中執行 Shell 指令碼。如果指令碼功能已停用,請選擇 Shortcuts > Settings,開啟 Advanced,並啟用 Allow Running Scripts。認識 macOS 的「捷徑」、「捷徑」進階設定

插入該行並建立獨立結果檔

將以下完整程式貼到 Run Shell Script。它要求提供一個現有的一般檔案,會在第 3 行之前插入 Birch,並在同一資料夾建立一個檔案,檔名是在來源路徑後加上 .inserted.txt。

#!/bin/sh
set -eu

fail() {
    printf '%s\n' "$1" >&2
    exit 1
}

[ "$#" -eq 1 ] || fail 'Select exactly one example text file.'
file=$1
line=3

case "$file" in
    /*) ;;
    *) fail 'The input must be an absolute file path.' ;;
esac

[ -f "$file" ] || fail 'The input file does not exist or is not a regular file.'
[ ! -L "$file" ] || fail 'Select the example file itself, not a symbolic link.'
[ -r "$file" ] || fail 'The input file cannot be read.'

count=$(/usr/bin/sed -n '$=' "$file") || fail 'Could not count the input lines.'
[ -n "$count" ] || fail 'The input file is empty.'
[ "$line" -le "$count" ] || fail 'The insertion line is beyond the end of the file.'

output="${file}.inserted.txt"
if [ -e "$output" ] || [ -L "$output" ]; then
    fail 'The output name already exists. Inspect or rename that result first.'
fi

if (
    set -C
    /usr/bin/sed "${line}i\\
Birch
" "$file" > "$output"
); then
    printf 'Created edited copy: %s\n' "$output"
else
    fail 'Could not finish the edited copy. Inspect any partial output before retrying.'
fi

sed 運算式中的實際換行是刻意安排的。請保留 i 後面的反斜線、接續的換行,以及獨立一行的插入文字。指令結構依循 Apple 發行的手冊,避免依賴從其他 sed 實作複製來的精簡插入寫法。sed 手冊:指令與插入文字

周圍的檢查條件是此工作流程的判斷規則。若要在指定行之前插入內容,該行必須存在。因此,這個程式會拒絕空檔案,以及目標行號大於最後一行的情況。它也會拒絕已存在的輸出檔名,而 Shell 的 noclobber 模式則在開啟輸出檔時再提供一道檢查。

指令碼會讀取原始檔並寫入另一個檔案。若寫入失敗,原始檔仍可使用,但可能會留下未完成的輸出檔。請將錯誤視為尚未完成的操作,並在移除或重試之前檢查該輸出檔。一次只執行一個執行個體,並在操作期間不要變更來源檔案。

此動作的輸出是包含路徑的文字狀態訊息,而不是「捷徑」的檔案物件。編輯後的檔案是由指令碼的重新導向建立。若之後加入 Save File,儲存的是動作輸出,而不是執行預期的行插入。「捷徑」文件說明 Save File 是檔案管理的分享動作,並未將其描述為可編輯指定行數的工具。關於 Mac「捷徑」中的分享動作

執行捷徑、檢查結果,並保留原始檔名

在 Finder 中,按住 Control 鍵並按一下這個一次性範例的 notes.txt 檔案,選擇 Quick Actions,再選擇 Insert Birch Before Line 3。Apple 說明了這種啟動方式。如果找不到該捷徑,請確認捷徑詳細資訊中已啟用 Finder,且其接受的輸入包含 Files。在 Mac 上工作時執行捷徑

執行成功後,範例資料夾會同時包含 notes.txt 和 notes.txt.inserted.txt。開啟後者,確認其內容完全如下:

Cedar
Maple
Birch
Willow

你也可以在「終端機」中使用以下完整指令檢查輸出:

/bin/cat "$HOME/Desktop/Line Insert Demo/notes.txt.inserted.txt"

若要讓編輯後的內容使用原始路徑,請關閉範例文件,並在 Finder 中進行以下兩次重新命名。先確認 notes.original.txt 尚未使用;如果該名稱已存在,請選擇其他尚未使用的備份名稱。

  1. 選取 notes.txt,按下 Return,將其重新命名為 notes.original.txt,再按一次 Return。
  2. 選取 notes.txt.inserted.txt,按下 Return,將其重新命名為 notes.txt,再按一次 Return。
  3. 開啟新命名的 notes.txt,並確認其中有四行。

Apple 說明了如何選取項目並按下 Return 重新命名。兩個名稱的最後 .txt 副檔名都要保留。如果 Finder 顯示名稱衝突,請停止操作並檢查現有項目,再選擇尚未使用的名稱。在 Mac 上重新命名檔案、資料夾和磁碟

這樣完成後,編輯後的內容會使用 notes.txt,原始內容則會使用 notes.original.txt。這會改變哪個檔案位於原始路徑;它不會保留原始檔案的身分,也不保證保留 Finder 標籤、延伸屬性或其他中繼資料。

調整插入內容,同時維持原意

處理另一個一次性檔案時,將 line=3 改為一個現有行號,並將 Birch 換成簡單的單行文字。請保留顯示的插入語法。本範例文字刻意不包含引號、美元符號、反引號或反斜線;任意文字需要額外的 Shell 和 sed 引號處理。

編輯指令碼前,請參考以下判斷表:

預期變更 做法
在第一行前放入文字 在非空的範例檔案中設定 line=1。
在另一個現有行前放入文字 將 line 設為該正整數行號。
在最後一行之後新增文字 使用獨立的附加操作;此程式會拒絕不存在的目標行。
插入到空檔案 另外建立初始內容;沒有現有行可供指定。
將同一捷徑執行兩次 先檢查先前的輸出。取代原始檔後再次執行,會再插入一份相同文字。

對於這項桌面操作,有用的檢查點包括選取的檔案、插入位置、完成的結果,以及最後的檔名。確認四行範例正確後,相同步驟就能讓你清楚地測試其他簡單的插入操作,同時保留起始文字。

來源