查找目录,其中缺少具有特定结尾的文件


10

我想显示所有目录,这些目录不包含以特定文件结尾的文件。因此,我尝试使用以下代码:

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

在此示例中,我想显示所有目录,这些目录不包含带有结尾的文件.ENDING,但这不起作用。

我的错误在哪里?


这不是不包含文件List目录的重复,因为该问题不涉及通配符。
Cristian Ciupitu 2014年

Answers:


7

这是三个步骤的解决方案:

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 shell,则没有临时文件的comm -3 <(find . -type f -name \*ENDING -exec dirname {} \; |sort -u) <(find . -type d |sort -u)
单线

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
Cristian Ciupitu 2014年

next(filter(lambda x: x.endswith('.ENDING'), filenames))也可以使用生成器理解来写next(x for x in filenames if x.endswith('.ENDING'))
Cristian Ciupitu 2014年

@CristianCiupitu:真相:find命令是hacky的,没有经过充分的测试。生成器理解-是的,这是另一种不错的方法。
MikeyB 2014年

1
我认为一个更好的解决方案是if not any(x.endswith('.ENDING') for x in filenames)基于以下事实:False空可迭代的任何回报。
Cristian Ciupitu 2014年

3

shell扩展了*,但是在您的情况下,不涉及任何shell,仅涉及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 2014年

我具有以下测试目录结构: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)`。但是,当我将.end更改为.xyz时,会得到相同的结果,这是因为我以have头作为目录名称,对吗?我该如何解决呢?

3
@bamboo我将放弃shell实用程序,而在此时寻找其他解决方案。
user9517 2014年

2

受到Dennis NolteMikeyB的回答的启发,我想出了以下解决方案:

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

它基于以下事实而工作:

如果设置了failglob shell选项,但未找到匹配项,则会显示一条错误消息,并且不执行该命令。

顺便说一下,这就是为什么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命令输出文件名

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.