特定の末尾のファイルが欠落しているディレクトリを見つける


10

特定のファイルで終わるファイルを含まないすべてのディレクトリを表示したいのですが。したがって、次のコードを使用してみました:

find . -type d \! -exec test -e '{}/*.ENDING' \; -print

この例では、末尾がのファイルが含まれていないすべてのディレクトリを表示したいのです.ENDINGが、これは機能しません。

私の間違いはどこですか?


この質問はワイルドカードを扱わないため、これはファイルを含まないListディレクトリの複製ではありません。
クリスティアンCiupitu 2014年

回答:


7

3つのステップでの解決策は次のとおりです。

temeraire:tmp jenny$ find . -type f -name \*ENDING -exec dirname {} \; |sort -u > /tmp/ending.lst
temeraire:tmp jenny$ find . -type d |sort -u > /tmp/dirs.lst
temeraire:tmp jenny$ comm -3 /tmp/dirs.lst /tmp/ending.lst 

2
Bashシェルを使用している場合、一時ファイルなしのワンライナー:comm -3 <(find . -type f -name \*ENDING -exec dirname {} \; |sort -u) <(find . -type d |sort -u)
Cristian Ciupitu 2014年

4

さあ行こう!

#!/usr/bin/env python3
import os

for curdir,dirnames,filenames in os.walk('.'):
  if len(tuple(filter(lambda x: x.endswith('.ENDING'), filenames))) == 0:
    print(curdir)

または代わりに(そしてより多くのpythonic):

#!/usr/bin/env python3
import os

for curdir,dirnames,filenames in os.walk('.'):
    # Props to Cristian Cliupitu for the better python
    if not any(x.endswith('.ENDING') for x in filenames):
        print(curdir)

ボーナスDLCコンテンツ!

(ほぼ)修正されたバージョンのfindコマンド:

find . -type d \! -exec bash -c 'set nullglob; test -f "{}"/*.ENDING' \; -print

ディレクトリに複数のファイルがある場合、検索ソリューションは失敗すると思います。test: ...: binary operator expected*.ENDING
クリスチャンCiupitu 2014年

next(filter(lambda x: x.endswith('.ENDING'), filenames))ジェネレータ内包表記を使用して書くこともできnext(x for x in filenames if x.endswith('.ENDING'))ます。
クリスティアンCiupitu 2014年

@CristianCiupitu:真実:findコマンドはハックで実際には完全にテストされていません。ジェネレーターの理解-ええ、それはそうするためのもう一つの良い方法です。
MikeyB 2014年

1
空のイテラブルのif not any(x.endswith('.ENDING') for x in filenames)戻り値Falseがあるという事実に基づいて使用すると、さらに優れたソリューションになると思います。
クリスチャンCiupitu 2014年

3

シェルはを展開*しますが、あなたの場合、シェルは含まれていません。findによって実行されるテストコマンドだけです。したがって、その存在がテストされるファイルは、文字通り名前が付けられます。*.ENDING

代わりに、次のようなものを使用する必要があります。

find . -type d \! -execdir sh -c 'test -e {}/*.ENDING' \; -print

これにより、テストの実行時にshが拡張されます。*.ENDING

ソース:UX.SEでグロビングを検索


動作しません。私は次のエラーを取得する:shが:-c: line 0: syntax error near unexpected token ( 『XYZ(dfdf) '`私のディレクトリ名は、フォーマットを持っている。』実際にはその口径のライブラリー。。

1
試してみるsh: line 0: test: foo1/bar.ENDING: binary operator expectedと、末尾がのファイルを含むディレクトリが表示されますENDING
ジェニーD

これは私にとってはプレーンなa.ENDINGファイル名で機能するようです
user9517

次のテストディレクトリ構造があります。test-> test(test)-> test.endingこのコードを使用した後、sh: -c: line 0: syntax error near unexpected token ( 'sh:-c:line 0:' test -e test(test)/ * 。ending ')を取得します。 / test(test) `。しかし、.endingを.xyzに変更しても同じ結果が得られます。これは、ディレクトリ名としてbractsがあるためです?どうすれば修正できますか?
bamboo

3
@bambooシェルユーティリティをあきらめて、この時点で別のソリューションを探します。
user9517 2014年

2

Dennis NolteMikeyBの答えに触発されて、私はこの解決策を思いつきました。

find . -type d                                                           \
  \! -exec bash -c 'shopt -s failglob; echo "{}"/*.ENDING >/dev/null' \; \
  -print 2>/dev/null

それはという事実に基づいて動作します

場合failglobのシェルオプションが設定され、一致するものが見つからない、エラーメッセージが出力され、コマンドが実行されません。

ところで、それがstderrがにリダイレクトされた理由/dev/nullです。


1

個人的にはperlでやる

#!/usr/bin/perl

use strict;
use warnings;

use File::Find;


#this sub is called by 'find' on each file it traverses. 
sub checkdir {
    #skip non directories. 
    return unless ( -d $File::Find::name );

    #glob will return an empty array if no files math - which evaluates as 'false'
    if ( not glob ( "$File::Find::name/*.ENDING" ) ) {
        print "$File::Find::name does not contain any files that end with '.ENDING'\n";
    }
}

#kick off the search on '.' - set a directory path or list of directories to taste.
#  - you can specify multiple in a list if you so desire. 
find (  \&checkdir, "." );

トリックを実行する必要があります(非常に単純なテストケースで機能します)。



0
find . -type d '!' -exec sh -c 'ls -1 "{}"|egrep -q "*ENDING$"' ';' -print
  • q egrepでは静かに

  • ではegrep、あなたが必要とすることを正規表現を入れ替えることができます

  • ls -1 "{}" findコマンドからファイル名を出力します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.