Shell-Script
循環遍歷目前目錄儲存目錄和數組中的子目錄名稱而不重複
我有一個場景,我循環遍歷給定路徑中的所有目錄和子目錄;如果找到具有特定副檔名 (.txt) 的文件,則將目錄和子目錄的名稱儲存在一個數組中。後來,我在這些目錄上讀取並執行命令。
這是我正在執行的操作:
!/bin/bash x=( $(find . -name "*.txt") ); echo "${x[@]}" for item in "${x[@]}"; { echo "$item"; }
我目前的輸出是:
./dir1/file1.txt ./dir1/file2.txt ./dir2/subdir1/subdir2/file3.txt
但我想要實現的是在數組
x
中不應該有任何重複,即使目錄包含多個.txt
文件。此外,我不想將文件名儲存為路徑;該數組應僅包含目錄名稱。預期輸出:
./dir1 ./dir2/subdir1/subdir2/
使用
bash
:shopt -s globstar shopt -s dotglob nullglob dirs=( ./**/*.txt ) # glob the names dirs=( "${dirs[@]%/*}" ) # remove the filenames at the end
這為您提供了一系列可能重複的目錄路徑。要刪除重複項,請使用關聯數組:
declare -A seen for dirpath in "${dirs[@]}"; do seen["$dirpath"]='' done dirs=( "${!seen[@]}" ) # extract the keys from the "seen" hash
然後,要列印它們,
printf '%s\n' "${dirs[@]}"
在
zsh
shell 中,您可以類似地執行此操作,但使用唯一數組和 shell 的花哨的萬用字元來去除路徑末尾的文件名:typeset -U dirs dirs=( ./**/*.txt(DN:h) )
模式後面的萬用字元中的
D
andN
充當dotglob
andnullglob
inbash
,即它們啟用隱藏名稱的匹配並在根本沒有匹配時刪除模式。最後:h
給你生成路徑名的“頭”,即最後沒有文件名的目錄路徑。
zsh
shell 不必顯式啟用使用,**
因為您必須bash
設置globstar
shell 選項。然後,要列印它們,
print -r -C1 -- $dirs
還有相關的: