Shell-Script

循環遍歷目前目錄儲存目錄和數組中的子目錄名稱而不重複

  • March 5, 2022

我有一個場景,我循環遍歷給定路徑中的所有目錄和子目錄;如果找到具有特定副檔名 (.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[@]}"

zshshell 中,您可以類似地執行此操作,但使用唯一數組和 shell 的花哨的萬用字元來去除路徑末尾的文件名:

typeset -U dirs

dirs=( ./**/*.txt(DN:h) )

模式後面的萬用字元中的DandN充當dotgloband nullglobin bash,即它們啟用隱藏名稱的匹配並在根本沒有匹配時刪除模式。最後:h給你生成路徑名的“頭”,即最後沒有文件名的目錄路徑。

zshshell 不必顯式啟用使用,**因為您必須bash設置globstarshell 選項。

然後,要列印它們,

print -r -C1 -- $dirs

還有相關的:

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