次のファイル階層があります。
data
├── debug.log
├── messages
│ ├── msg001.txt
│ ├── msg002.txt
│ └── msg003.txt
└── pictures
├── msg002
│ └── pic001.jpg
└── msg003
├── pic001.jpg
└── pic002.jpg
最初の2つのレベル(データ、データ/メッセージ、データ/画像)の下のすべてのファイルとすべてのディレクトリを見つけたいです。階層の固定構造の一部ではないすべて(該当する場合)。
シングル検索呼び出しでこれを実行できますか?
次のファイルがあります。
$ find data -type f | sort
data/debug.log
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002/pic001.jpg
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg
ディレクトリを見つけることができます:
$ find data -mindepth 2 -type d | sort
data/pictures/msg002
data/pictures/msg003
ただし、-minlengthはテストではなくオプションなので、それらを組み合わせることはできません。
$ find data -type f -o \( -mindepth 2 -type d \) | sort
find: warning: you have specified the -mindepth option after a non-option argument -type, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002
data/pictures/msg002/pic001.jpg
data/pictures/msg003
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg
(data/debug.logはここにありません。)
階層の深さを実際のテストと見なす方法はありますか?
私が考えることができる最高の組み合わせは、パスで正規表現を使用してディレクトリの最初の2つのレベルを識別することです。
$ find data -type f -o \( -type d -regextype posix-extended \! -regex 'data(/[^/]+)?' \) | sort
答え1
階層の深さを実際のテストと見なす方法はありますか?
にありますFreeBSDを探す、-depth N
条件もあります:
% find data -type f -o -depth +1 -type d |sort
data/debug.log
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002
data/pictures/msg002/pic001.jpg
data/pictures/msg003
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg
(はい、-depth
そのオプションと混同しやすいです。)
「固定構造」(IMO、構造が実際に固定されているかどうかを知る必要があります)の一部であるディレクトリのセットを知っている場合は、次のディレクトリを除外できます。
% find data ! -path data ! -path data/messages ! -path data/pictures
...
またはgrepと同じです。
% find data | grep -vEe '^(data|data/(pictures|messages))$'
...
find
(代わりにデフォルトの出力形式を使用したため、find -print0
ファイル名に改行文字が含まれていない可能性があります)
答え2
これは-mindepth
非標準拡張です(もともとはGNUから来ましたが、find
後で他の実装に追加されます)。対照的に-maxdepth
、標準述部で簡単にシミュレートされます。たとえば、LC_ALL=C find . -path './*/*'
GNUエミュレーションですfind . -mindepth 2
。
だからここにあります:
LC_ALL=C find data '(' -type d -path '*/*/*' -o -type f ')' -print0 |
sort -z |
tr '\0' '\n'
find
sort
(ファイルパスは複数行で構成される可能性があるため、NULで区切られたレコードを使用しない限り、出力をパイプで接続することはできません。-print0
現在は一般的ですが(すぐにPOSIXになる予定ですが、あまり一般的ではありません)、-z
GNU拡張です。-print0
-z
答え3
最善の方法ではありませんが、GNUを使用して次のことができますfind
。
find data -printf '%d\0%y\0%p\n' | awk -F '\0' '$2 == "f" || $2 == "d" && $1 >= 2 {print $3}'
find
この-printf
フラグを使用すると、次のフィールドが印刷されます(ヌル文字 - で区切られます\0
)。
%d File's depth in the directory tree; 0 means the file is a starting-point.
%y File's type (like in ls -l), U=unknown type (shouldn't happen)
%p File's name.
その後、コマンドはawk
深さが2()以上のすべてのファイル()とディレクトリの名前を印刷します。$2 == "f"
$2=="d" && $1 >= 2
答え4
免責事項:私はこの回答に使用されている生皮(rh)プログラムの現在の作成者です(参照https://github.com/raforg/rawhide)。
そして右回転、次のようにすることができます。
rh data 'f || (d && depth >= 2)'
ディレクトリ内の少なくとも2()の深さのdata
ファイル(f
)とディレクトリ()を検索します。d
depth >= 2
Linux、FreeBSD、OpenBSD、NetBSD、macOS、Solaris、およびCygwinで動作します。