比方說,我有一個包含數百或數千個文件的資料夾,所有文件均以以下架構命名:
<random number of variable length>_<date code in YYYYMMDD format>.jpg
例子:
73923_20180927.jpg
4457582_20180927.jpg
...
18733557_20190401.jpg
23573_20190401.jpg
...
我期望 bash 腳本執行的操作是列印這些日期代碼的列表,即
20180927
20190401
...
這聽起來像是一項更容易的任務,但實際上是一項更容易的任務。由於架構始終相同,因此我已經實作了應用字串操作,以便僅列印檔案名稱的所需部分。但是,我仍在弄清楚如何僅列印每個日期一次。
有沒有一個巧妙的方法來解決這個問題?
答案1
假設檔案名稱全部符合模式./*_*.jpg
:
for name in ./*_*.jpg; do
name=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
printf '%s\n' "${name%.jpg}" # 20180927.jpg --> 20180927
done | sort -u
這會迭代所有名稱。對於每個名稱,它會刪除匹配的最長前綴字串*_
。然後它輸出刪除後綴的剩餘字串.jpg
。
然後對所有字串進行排序,以便最後只輸出唯一字串的清單。
如果存在目錄可能為空的風險,則應nullglob
在循環 ( shopt -s nullglob
) 之前設定 shell 選項。這將使循環根本不運行,而不是使用 中未擴展的通配模式運行一次$name
。
沒有特殊原因,這是如何做到這一點的sort
:
declare -A skip=()
for name in ./*_*.jpg; do
key=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
key=${key%.jpg} # 20180927.jpg --> 20180927
if [[ ! -v skip[$key] ]]; then
printf '%s\n' "$key"
skip[$key]=1
fi
done
在這裡,我追蹤哪些字串已作為關聯數組 中的鍵輸出skip
。如果字串對應於陣列中的某個鍵,則不會輸出該字串。
答案2
假設確實沒有不正確的檔案名,則在該目錄中執行:
ls -U | awk '-F[_.]' '{ print $2 }' | sort | uniq