如何获取不包括任何基本/父路径的最深唯一目录路径的列表

如何获取不包括任何基本/父路径的最深唯一目录路径的列表

我想要一个在 Linux 上运行并且可以跨 shell(不仅仅是 bash)和文件系统(包括 drvfs 或 btrfs)移植的解决方案 注意:目录名称可能包含空格

通过 find,我可以生成以文件夹为根的所有路径的列表,如下所示:

find -type d
.
./a dir
./a dir/20210101
./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var
./a dir/20210101/var/log
./a dir/20211201
./b dir
./b dir/20210212
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir
./d dir/20210711

然而,我想排除已经包含在最深的唯一路径中的“基”或“父”路径。还请帮助使用正确的术语来描述这一点,因为我觉得我没有使用最佳的描述。

我可以使用基本脚本来完成此操作,但假设有一种更优雅的方法,使用以下方法之一:

  • 寻找
  • LS

这是我的脚本:

save_ifs=$IFS;
IFS=$'\n';
prev_path="";
for path in $(find -depth -type d); do

    if [ ! ${#path} -lt ${#prev_path} ]; then
        echo $path;
    fi
    
    prev_path=$path;

done

及其输出 - 这是所需的输出

./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var/log
./a dir/20211201
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir/20210711

答案1

这看起来像是相反的变体从文本文件中过滤掉比直接前一个路径更深的路径

因此,修改我的答案,这是一个选择:

tac input.txt | awk '
   { sub(/\/?$/, "/") }
   NR == 1 || substr(prev, 0, length($0)) != $0 { print }
   { prev = $0 }; ' | tac | sed -e 's/\/$//'

或者

cat input.txt | awk '
    { sub(/\/?$/, "/") }
    NR != 1 && substr($0, 0, length(prev)) != prev {print prev}
    { prev = $0 }
    END { print }; ' | sed -e 's/\/$//'

根据第一个列表中的输入,两者都会给出:

./a dir/20210101/bin
./a dir/20210101/etc
./a dir/20210101/var/log
./a dir/20211201
./b dir/20210212/bin
./b dir/20210212/etc
./c dir
./d dir

假设输入是有序的,以便目录的内容紧接在该目录之后(即深度优先,预先排序),这就是 的输出find应该类似于(*)的内容,并且与 C 语言中的字典排序相匹配语言环境会给出。

(除非您使用-depth,这与名称所暗示的不同,会切换到后排序,但仍然是深度优先搜索。)

答案2

编辑:改写回复,代码不变。

默认 深度优先搜索find . -type d在子目录之前输出父目录(如果有),因此跳过紧接着子目录的行(一个附加子目录)。这是带有 POSIX 的单行代码脚本。假定路径名没有换行符。

find . -type d | sed -e '$!N' -e '/\(.*\)\n\1\//!P' -e 'D'

在哪里:

  • 标准N; …; P; D;命令序列打开一个滑动的两行窗口进行输入
  • 除非在最后一行 ( $!) 将\n+下一行追加到模式空间 ( N)
  • 如果第二行与第一行不匹配,后跟/( \1\/) 打印第一行 ( P)
  • 删除第一行并恢复循环 ( D)

相关内容