$ find ./ | tac
./dir1/file -> "abc"
./dir1
./dir2/file - > "abc"
./dir2
./dir3/file -> "xyz"
./dir3/dir3_1/file - > "abc"
./dir3/dir3_1
./dir3
または
$ tree
├── dir1
│ └── file -> "abc"
├── dir2
│ └── file -> "abc"
└── dir3
├── dir3_1
│ └── file -> "abc"
└── file -> "xyz"
dirs tree(ファイルなし)を表示する必要があるのは、「abc」値を含む「file」ファイルを持つものだけです。
コマンドがあることを知っていますtree -P 'file*'
ファイル名でツリーをフィルタリングするには、コンテンツを「grep」してツリーをフィルタリングする方法もあるかもしれません。
私はまた、このようなことをするというアイデアを思いつきました(もちろんそれは機能しません):
$(find ./ -type f -exec grep abc {} +;) | tree -d
そしてどういうわけかフラットなfind
の結果をtree
コマンドに送信します。
tree --fromfile
の使用私のDebian10には、tree v1.8.0
があります。 --fromfile
をサポートします。
--fromfile
ファイルシステムではなくファイルからディレクトリリストを読み取ります。コマンドラインで提供されるパスは、検索するディレクトリではなく、読み取るファイルです。ドット(.
)ディレクトリは、tree
が標準入力からパスを読み取る必要があることを示します。
このようにして、tree
またはgrep -rl
からの出力をfind
にフィードできます。
grep -rl abc | tree -d --fromfile .
問題:
一致するファイルがまったくない場合でも、.
が報告されます。
tree
が/foo/whatever
またはfoo/whatever
を読み取る場合、foo
は.
の-サブディレクトリとして報告されます。同様に、./whatever
の場合:.
は.
という名前の追加レベルとして報告されます。したがって、grep -rl abc /foo
、grep -rl abc .
、find /foo
、またはfind .
を使用すると、結果が正式な期待を完全に満たすとは限りません。
改行を含むファイル名はtree
を混乱させます。 tree
に対応するスイッチがないため、grep -Z
またはfind -print0
を使用することはできません。
foo/bar/
内の一致ファイルとfoo/
内の一致ファイルは、foo/bar/
内の一致ファイルと同じ出力を生成します。 foo/bar
ブランチが表示されている場合、foo/
に一致するファイルがあるかどうかはわかりません。これは仕様の欠陥です。
次のコードは--fromfile
を使用していません。上記の問題のいくつかは修正されますが、速度は遅くなります。
#!/bin/sh
tmp="$(mktemp -d)"
[ "$?" -eq 0 ] || exit 2
trap 'rm -r "$tmp"' INT TERM EXIT
dir="${2:-.}"
cd "$dir" || exit 1
find . -type f -exec grep -q "$1" {} \; -exec sh -c '
cd "$1" || exit 1
shift 1
for d; do
mkdir -p "top/$(dirname "$d")"
done
' sh-find "$tmp" {} +
cd "$tmp" || exit 1
[ -d "top" ] || exit 0
printf "%s\n" "$dir"
tree -d --noreport "top" | tail -n +2
使用法:scriptname pattern /path/to/dir
またはscriptname pattern
(この場合、.
がデフォルトのディレクトリです)。
一般的な手順は次のとおりです。
tree -d
を使用します(出力を調整して、元のディレクトリパスが一時トップノードを置き換えるようにします)。top
という名前のディレクトリは、少なくとも1つ一致する場合にのみ作成されることに注意してください。このようにして、一致したかどうかを判断できます。空の出力(終了ステータス0
)は、一致するものがまったくなかったことを示します。