Shell-Script

如何在 -exec 腳本中增加 COUNTER?

  • November 20, 2021

上下文:zsh Catalina MacOS:

可執行腳本BatesStamp 使用imagemagick 將數字標記到 jpg 文件中:

# BatesStamp: OVERWRITES and stamps ONE file with COUNTER  (upper left corner)
# usage  ./BatesStamp  COUNTER  PATH_FILE   
# to be used with find & -exec: https://unix.stackexchange.com/a/96239/182280   


COUNTER=$1     # 1st argument = number to be stamped upon .jpg file
PATH_FILE=$2   # 2nd argument = /path_to_file/Filename.jpg

convert $PATH_FILE  -auto-orient -gravity northWest  -font "Arial-Bold-Italic" -pointsize 175 \
  -fill red  -annotate +30+30   "$COUNTER"  $PATH_FILE;
  ((COUNTER++))  #https://stackoverflow.com/a/21035146/4953146
  echo "watermarked i= $COUNTER  $PATH_FILE"

目標是用唯一編號標記目錄樹中的所有 .jpg 文件。我相信每次呼叫 $COUNTER 時都必須增加它:這確保每個文件都帶有唯一的編號。該策略是遍歷所有子目錄find以辨識 .jpg 文件,並使用 $COUNTER++ 對每個 .jpg 文件進行 BatesStamp。

此腳本goBatesStamp.sh遍歷子目錄以執行每個要由BatesStamp處理的 .jpg 文件

# goBastesStamp.sh
cd /Users/user/Desktop/AITH_USB_Hope_Submitted_MyCloud/PhotoGraphs_Work/A_Building_NoBulkhead. # navigate to top level directory
COUNTER=100   # initialize COUNTER
find /Users/user/Desktop/AITH_USB_Hope_Submitted_MyCloud/PhotoGraphs_Work/A_Building_NoBulkhead -iname "*.jpg" -exec ./BatesStamp $((COUNTER+=1)) {} \;  

問題在於以命令開頭的行find。具體來說, COUNTER 不會增加。

測試表明 .jpg 文件標有數字 100 它表明 $((COUNTER++)) 是問題所在。將 COUNTER 遞增 1 並將遞增的 COUNTER 輸入 ./BatesStamp 的正確語法是什麼?

在裡面

find ... -exec ./BatesStamp $((COUNTER+=1)) {} ';'

shell 程式碼,$((COUNTER+=1))在呼叫命令之前由解釋該命令行的 shell 擴展find,因此find被呼叫為:

find ... -exec ./BateStamp 101 {} ';'

對於它找到的每個文件,它都會呼叫./BateStamp 101 path/to/the/file.

即使您將其更改為:

export COUNTER=100
find ... -exec sh -c 'for f do ./BatesStamp "$((COUNTER+=1))"; done' sh {} +

forfind啟動一個增加自己的$COUNTER變數並在循環中處理多個文件的 shell,它仍然無法正常工作,因為findwith-exec cmd {} +可能仍然會呼叫cmd多次,每次呼叫一批文件,並且sh上面的每次呼叫都會再次從 100 開始。

在這裡,您需要一次呼叫 sh 或其他某種 shell 或程式語言,以便在一次呼叫中處理所有文件。

由於您已經在使用zsh,您應該能夠:

#! /bin/zsh -

top=/Users/user/Desktop/AITH_USB_Hope_Submitted_MyCloud/PhotoGraphs_Work/A_Building_NoBulkhead
n=100
for file in $top/**/*.jpg(NDn.); do
 mogrify -auto-orient \
         -gravity northWest \
         -font "Arial-Bold-Italic" \
         -pointsize 175 \
         -fill red \
         -annotate +30+30 $n \
         -- $file &&
   print -ru2 -- $file was watermarked with $n
 (( n++ ))
done

此處使用zsh 遞歸 glob**/匹配 0 級或更多級別的子目錄)而不是find查找jpg文件(僅限於具有. glob 限定符的正常文件,並使用 ¹ 對輸入列表進行數字排序,n而不是像那樣以隨機順序處理它們find)並mogrify改用因為convert這是 ImageMagick 命令來就地編輯圖像。

請注意,對於要由解釋器解釋而不是sh直接執行的腳本,您需要一個 she-bang 行 ( #! /path/to/the/interpreter) 來告訴系統使用哪個解釋器來解釋文件的內容。或者您可以在 file: 上手動呼叫解釋器zsh /path/to/that/file,或者讓您目前使用的互動式 shell(如果 zsh)直接使用source /path/to/that/file或在子 shell 中解釋它,這樣它就不會改變使用(source /path/to/that/file).


¹ 如果沒有nnumericglobsort也可以全域啟用的選項)glob 限定符,則排序是詞法的,因此image2.jpg例如會在排序之後 image10.jpg出現,因為在排序規則2之後。1

² 如果您想知道shebang-中的額外內容,請參閱為什麼“#!/bin/sh -”shebang 中的“-”?#! /bin/zsh -

引用自:https://unix.stackexchange.com/questions/678343