プライマリ/親パスを除いて最も深い一意のディレクトリパスのリストを取得する方法

プライマリ/親パスを除いて最も深い一意のディレクトリパスのリストを取得する方法

Linux上で実行され、シェル(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

ただし、最も深い固有のパスにすでに含まれている「基本」または「親」パスを除外したいと思います。また、最善の説明を使用していないようですが、正しい用語を使用して説明するのに役立ちます。

デフォルトのスクリプトを使用してこれを実行できますが、よりエレガントな方法があると仮定した場合は、次のいずれかを使用してください。

  • 探す
  • エルエス

これは私のスクリプトです。

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(使用しない限り

おすすめ記事