Bash

查找僅包含隱藏文件和/或隱藏目錄的所有目錄

  • June 15, 2021

問題

  • 我一直在努力製作一個 Bash 命令,該命令能夠遞歸地搜尋目錄,然後返回包含專有隱藏文件和/或隱藏目錄的每個子目錄(直到某個最大深度)的路徑。

視覺解釋

  • 考慮以下文件系統摘錄:
+--- Root_Dir
|   +--- Dir_A
|   |   +--- abc.txt
|   |   +--- 123.txt
|   |   +--- .hiddenfile
|   |   +--- .hidden_dir
|   |   |   +--- normal_sub_file_1.txt
|   |   |   +--- .hidden_sub_file_1.txt
|   |     
|   +--- Dir_B
|   |   +--- abc.txt
|   |   +--- .hidden_dir
|   |   |   +--- normal_sub_file_2.txt
|   |   |   +--- .hidden_sub_file_2.txt
|   |    
|   +--- Dir_C
|   |   +--- 123.txt
|   |   +--- program.c
|   |   +--- a.out
|   |   +--- .hiddenfile
|   |   
|   +--- Dir_D
|   |   +--- .hiddenfile
|   |   +--- .another_hiddenfile
|   |     
|   +--- Dir_E
|   |   +--- .hiddenfile
|   |   +--- .hidden_dir
|   |   |   +--- normal_sub_file_3.txt   # This is OK because its within a hidden directory, aka won't be checked
|   |   |   +--- .hidden_sub_file_3.txt
|   | 
|   +--- Dir_F
|   |   +--- .hidden_dir
|   |   |   +--- normal_sub_file_4.txt
|   |   |   +--- .hidden_sub_file_4.txt

期望的輸出

  • 我正在尋找的命令將輸出
./Root_Dir/Dir_D
./Root_Dir/Dir_E
./Root_Dir/Dir_F
  • Dir_D因為它只包含隱藏文件。
  • Dir_E因為它只包含我正在搜尋的級別的隱藏文件和隱藏目錄。
  • Dir_F因為它只包含我正在搜尋的級別的隱藏目錄。

嘗試

  • 我試圖使用該find命令來獲得我正在尋找的結果,但我似乎無法弄清楚我需要將輸出傳遞到哪些其他命令或我應該使用哪些其他選項。
  • 我認為可行的命令如下所示:
bob@linux:/$ find ./Root_Dir -mindepth 2 -maxdepth 2 -type d -name "*." -type -f -name "*." | command to see if these are the only files in that directory  

我對此有一個不太漂亮的解決方案。

以腳本形式:

#!/bin/bash

# Echo whatever is passed to fail, and then exit with a status of 1
fail() {
 echo >&2 "$@"
 exit 1
}

# If the number of arguments are less or more than what
# we expect, throw help syntax and exit.
if [ $# -gt 2 ] || [ $# -lt 2 ]
then
 fail "
$0 check for directories that only contain hidden listings
Usage: $0 <Directory to search from> <Depth to check>
 "
fi

# Assign parameters
root_dir=$1
depth=$2

# Find a list of directories that contain files OR subdirectories
# that are hidden
readarray -t dirs < <(export LC_ALL=C
 find "$root_dir" -mindepth "$depth" -maxdepth "$depth" \
   -name ".*" \( -type d -o -type f \) -execdir pwd \; | sort -u
)

# Of the dirs we found, do any of them return any listings with a
# default ls execution? If so, that directory cannot only contain
# hidden listings.
final=()
for dir in "${dirs[@]}"
do
 notExclusive="$(ls -- "$dir")"
 if [ "$notExclusive" = "" ]
 then
    final+=("$dir")
 fi
done

# The array final contains the directories who only contain hidden
# files/subdirectories.
printf '%s\n' "${final[@]}"

基本上我們只是找到包含隱藏列表的目錄(在問題中指定的深度為 2),將它們載入到數組中,如果ls沒有標誌不返回任何內容,我們可以得出結論,只有隱藏列表包含在目錄中,符合我們的標準。

為了解釋為什麼您只需要find根據 OP 的評論呼叫一次。該命令find具有基本邏輯的運算符, -a 連接兩個表達式邏輯 AND 時的預設行為,! 如在邏輯 NOT 中,-o 在邏輯 OR 中。

此方法假定目錄路徑不包含換行符,如果包含換行符,readarray則會錯誤地分隔每個目錄路徑。

醜陋的“單線”:

readarray -t dirs < <(export LC_ALL=C; find ./Root_Dir -mindepth 2 -maxdepth 2 -name '.*' \( -type d -o -type f \)  -execdir pwd \; | sort -u); final=(); for dir in "${dirs[@]}"; do notExclusive="$(ls -- "$dir")"; if [ "$notExclusive" = "" ]; then final+=("$dir"); fi; done; printf '%s\n' "${final[@]}"

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