回答:
これは、GNU find
とに基づく完全に異なるアプローチですuniq
。これは、検出された各ディレクトリのファイルをカウントするシェルコマンドの実行に基づく回答よりもはるかに高速で、CPUフレンドリーです。
find . -type f -printf '%h\n' | sort | uniq -d
このfind
コマンドは、階層内のすべてのファイルのディレクトリを印刷し、uniq
少なくとも2回表示されるディレクトリのみを表示します。
-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
find . -type d \
-exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
-print
これにより、現在のディレクトリ内またはその下のすべての名前が検索され、ディレクトリの名前ではないすべての名前が除外されます。
残りのディレクトリ名は、この短いスクリプトに付けられます。
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
このスクリプトは、最初のコマンドライン引数(からfind
)として指定されたディレクトリ内の(シンボリックリンクをスキップする)通常のファイルの数をカウントします。スクリプトの最後のコマンドは、カウントが2以上かどうかを確認するテストです。このテストの結果は、スクリプトの戻り値(終了ステータス)です。
テストが成功した場合は、-print
原因となるfind
ディレクトリへのパスをプリントアウトします。
隠しファイル(名前がドットで始まるファイル)も考慮するには、sh -c
スクリプトを次のように変更します。
for n in "$1"/*; do
に
for n in "$1"/* "$1"/.*; do
テスト:
$ tree
.
`-- test
|-- a
|-- dir1
| |-- a
| |-- b
| `-- c
`-- dir2
|-- dira
|-- dirb
| |-- file-1
| `-- file-2
`-- dirc
6 directories, 6 files
$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb
[ "" -ge 2 ]
有効なテストであるため、ディレクトリに通常のファイルがなければエラーはありません。
dash
、bash --posix
およびtest
すべてがエラーメッセージを表示し、2で終了します(つまり、「エラーが発生しました」)
ksh
として実行されているシステムでテストしていましたsh
。すぐに修正されます。私をつついてくれてありがとう!:-)
[ -f ... ]
シンボリックリンクを逆参照します。質問では、通常のファイルのみをカウントするように指定されているため、テストを追加してそれらを排除する必要があります。
SUに関するGillesの回答の助けを借りてと、ここで何が必要か、その逆といくつかの変更、。
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
ディレクトリツリー。
.
├── test
│ ├── dir1
│ │ ├── a
│ │ ├── b
│ │ └── c
│ ├── dir2
│ │ ├── dira
│ │ │ └── a file\012with\012multiple\012line
│ │ ├── dirb
│ │ │ ├── file-1
│ │ │ └── file-2
│ │ └── dirc
│ ├── diraa
│ ├── dirbb
│ ├── dircc
│ └── x
│ └── x1
│ └── x2
└── test2
├── dir3
└── dir4
結果:
./test
./test/dir1
./test/dir2/dirb
test
とdir2
ディレクトリの両方を見つけます(私の答えを参照してください)。
test/x1
とtest/x2
同様のファイルとして... $1
と$2
のディレクトリとなりtest
、およびディレクトリを見逃すことになります。
別のfind
+ wc
アプローチ:
find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print
path/currdir
-現在のディレクトリへのパス
-maxdepth 1
- 直接の子サブフォルダーのみを検討する
! -empty
-空のサブフォルダーを無視
! -path "path/currdir"
-現在のディレクトリパスを無視する
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
見つかった各サブフォルダのファイル数が割り当てられます
[ $count -ge 2 ] ... -print
-2つ以上の通常のファイルを含むサブフォルダー名/パスを印刷する
find
。この場合、GNUfind
は現在のロケール(Cロケールの "ä"など)で印刷できない文字を含むディレクトリの名前を壊すためです。unix.stackexchange.com/questions/321697/…