Shell

遞歸列出所有包含一個或多個 jpg 圖像文件的目錄

  • February 5, 2021

我正在嘗試整理我的照片,由於各種歷史原因,這些照片分散在我的系統中。為了讓我能夠開始這項任務,我一直在嘗試使用命令行來建構包含一個或多個 jpg 文件的所有目錄的列表。我確定我不必擔心尋找其他圖像文件格式,但我必須允許 jpg 以大寫和小寫形式出現。

我希望每個目錄名稱在最終列表中只出現一次。舉個例子,如果我有以下目錄,每個目錄都包含一個或多個 jpg 或 JPG 文件….

~Mike/Pictures
~Mike/Pictures/London/Olympics
~Mike/Pictures/London
~Mike/Pictures/London/Holiday
~Mike/Photos
~Mike/Family History/Swaine

我希望每個目錄只列出一次結果 - 無論它可能包含多少圖像文件 - 最好先排序然後寫入文件

~Mike/Family History/Swaine
~Mike/Photos
~Mike/Pictures
~Mike/Pictures/London
~Mike/Pictures/London/Holiday
~Mike/Pictures/London/Olympics

我的命令行技能達不到這個!我可以使用許多簡單形式的單個命令,但是一旦它們變得複雜和/或必須通過管道傳輸,事情往往會出錯。

假設 JPEG 圖像文件具有後綴.jpg

find "$HOME" -type f -name '*.jpg' \
   -exec sh -c 'for d; do dirname "$d"; done' sh {} + | sort -u -o jpeg_dirs.txt

這取決於您沒有名稱中帶有換行符的時髦目錄名稱。

使用 GNU find

find "$HOME" -type f -name '*.jpg' -printf '%h\n' | sort -u -o jpeg_dirs.txt

這些find命令將在您的主目錄下查找所有 JPEG 圖像並列印找到它們的目錄的名稱。將sort -u獲取此目錄名稱列表,對其進行排序並刪除重複項。結果將寫入jpeg_dirs.txt目前目錄中的文件。


在 2021 年初(3.3 年後)回顧這一點,我有點畏縮,因為我上面的解決方案雖然本身沒有錯,但有點倒退。它還對“好文件名”(沒有換行符)做出了明顯的假設。

當您使用find搜尋目錄時,不要像我上面那樣搜尋正常文件;實際搜尋目錄。一旦我們有了目錄,我們就可以查看它們中的每一個,看看它是否是一個匹配的文件*.jpg或者*.JPG(其他文件名後綴很容易添加):

find "$HOME" -type d -exec bash -O nullglob -O dotglob -O extglob -c '
   for dirpath do
       set -- "$dirpath"/*.@(jpg|JPG)
       [[ "$#" -gt 0 ]] && printf "%s\n" "$dirpath"
   done' bash {} +

這會從您的主目錄向下窺視每個目錄,並嘗試在每個目錄中擴展通配模式*.@(jpg|JPG)。這個模式也可以寫成兩個獨立的模式,*.jpg並且*.JPG匹配我們要查找的所有文件。如果一個名稱匹配,我們假設這是一個我們想要輸出名稱的目錄。這將為僅包含具有這些後綴的子目錄的目錄提供誤報。

我們執行內部腳本時使用的 shell 選項允許我們匹配bash隱藏的名稱(通配模式。dotglob``nullglob``ksh``@(...|...)

使用zsh外殼:

typeset -U list=(~/**/*.(jpg|JPG)(.DN:h))
print -rC1 $list

這將創建一個數組變數 ,list它具有隻儲存唯一元素的屬性。它被初始化為擴展文件名通配模式的結果。該模式匹配主目錄中或主目錄下的所有 JPEG 圖像文件,:h最後從生成的路徑名中刪除實際文件名。使.模式只匹配正常文件,並且D和.N``dotglob``nullglob``bash

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