查找所有仅包含隐藏文件的目录 and/or 个隐藏目录
Find all directories that contain only hidden files and/or hidden directories
问题
- 我一直在努力编写一个 Bash 命令,该命令能够递归搜索目录,然后 return 每个子目录的路径(达到某个最大深度)仅包含 个 个隐藏文件 and/or 个隐藏目录。
视觉解释
- 考虑以下文件系统摘录:
+--- 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
命令来获得我正在寻找的结果,但我似乎无法弄清楚我需要将输出传输到什么其他命令或我应该使用什么其他选项正在使用。
- 我认为可行的命令如下所示:
$ 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
假设这个结构,你不需要find
。
根据需要调整图案。
for d in $ROOT_DIR/Dir_?/; do
lst=( $d* ); [[ -e "${lst[0]}" ]] && continue # normal files, skip
lst=( $d.* ); [[ -e "${lst[2]}" ]] || continue # NO hidden, so skip
echo "$d"
done
我在我的 /tmp
目录中重建了你的文件结构并将其保存为 tst
,所以
$: ROOT_DIR=/tmp ./tst
/tmp/Dir_D/
/tmp/Dir_E/
/tmp/Dir_F/
请注意,隐藏文件的确认使用"${lst[2]}"
,因为前2个总是.
和..
,这不算。
你或许可以使用 for d in $ROOT_DIR/*/
.
我想这对你有用。 (mindepth=2, maxdepth=2)
如果您需要更深的子目录(mindepth=3,maxdepth=3),您可以添加一个级别 -
for d in $ROOT_DIR/*/*/
and/or 两者(mindepth=2,maxdepth=3)
for d in $ROOT_DIR/*/ $ROOT_DIR/*/*/
或者如果您不想要mindepth/maxdepth,
shopt -s globstar
for d in $ROOT_DIR/**/
解析 find 的输出不是一个好主意; -exec 存在,sh 可以在不破坏任何东西的情况下进行过滤。
find . -type d -exec sh -c '
for d; do
for f in "$d"/*; do
test -e "$f" &&
continue 2
done
for f in "$d"/.[!.]* "$d"/..?*; do
if test -e "$f"; then
printf %s\n "$d"
break
fi
done
done' sh {} +
您可以使用 find 提供的任何扩展来调整深度。
如果您的文件名不包含换行符,这将起作用。
find -name '.*' | awk -F/ -v OFS=/ '{ --NF } !a[[=10=]]++'
问题
- 我一直在努力编写一个 Bash 命令,该命令能够递归搜索目录,然后 return 每个子目录的路径(达到某个最大深度)仅包含 个 个隐藏文件 and/or 个隐藏目录。
视觉解释
- 考虑以下文件系统摘录:
+--- 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
命令来获得我正在寻找的结果,但我似乎无法弄清楚我需要将输出传输到什么其他命令或我应该使用什么其他选项正在使用。 - 我认为可行的命令如下所示:
$ 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
假设这个结构,你不需要find
。
根据需要调整图案。
for d in $ROOT_DIR/Dir_?/; do
lst=( $d* ); [[ -e "${lst[0]}" ]] && continue # normal files, skip
lst=( $d.* ); [[ -e "${lst[2]}" ]] || continue # NO hidden, so skip
echo "$d"
done
我在我的 /tmp
目录中重建了你的文件结构并将其保存为 tst
,所以
$: ROOT_DIR=/tmp ./tst
/tmp/Dir_D/
/tmp/Dir_E/
/tmp/Dir_F/
请注意,隐藏文件的确认使用"${lst[2]}"
,因为前2个总是.
和..
,这不算。
你或许可以使用 for d in $ROOT_DIR/*/
.
我想这对你有用。 (mindepth=2, maxdepth=2)
如果您需要更深的子目录(mindepth=3,maxdepth=3),您可以添加一个级别 -
for d in $ROOT_DIR/*/*/
and/or 两者(mindepth=2,maxdepth=3)
for d in $ROOT_DIR/*/ $ROOT_DIR/*/*/
或者如果您不想要mindepth/maxdepth,
shopt -s globstar
for d in $ROOT_DIR/**/
解析 find 的输出不是一个好主意; -exec 存在,sh 可以在不破坏任何东西的情况下进行过滤。
find . -type d -exec sh -c '
for d; do
for f in "$d"/*; do
test -e "$f" &&
continue 2
done
for f in "$d"/.[!.]* "$d"/..?*; do
if test -e "$f"; then
printf %s\n "$d"
break
fi
done
done' sh {} +
您可以使用 find 提供的任何扩展来调整深度。
如果您的文件名不包含换行符,这将起作用。
find -name '.*' | awk -F/ -v OFS=/ '{ --NF } !a[[=10=]]++'