Tìm thư mục, trong đó các tệp có một kết thúc cụ thể bị thiếu


10

Tôi muốn hiển thị tất cả các thư mục, không chứa các tệp có một tệp cụ thể kết thúc. Vì vậy, tôi đã thử sử dụng mã sau đây:

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

Trong ví dụ này tôi muốn hiển thị tất cả các thư mục, không chứa các tệp có phần kết thúc .ENDING, nhưng điều này không hoạt động.

Lỗi của tôi ở đâu?


Đây không phải là bản sao của các thư mục Danh sách không chứa tệp vì câu hỏi đó không liên quan đến ký tự đại diện.
Cristian Ciupitu

Câu trả lời:


7

Đây là một giải pháp trong ba bước:

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
Một lớp lót không có tệp tạm thời nếu sử dụng shell Bash:comm -3 <(find . -type f -name \*ENDING -exec dirname {} \; |sort -u) <(find . -type d |sort -u)
Cristian Ciupitu

4

Chúng ta đi đây!

#!/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)

Hoặc xen kẽ (và nhiều 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)

Thưởng nội dung DLC!

Phiên bản đã sửa (hầu hết) của lệnh find:

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

Tôi nghĩ rằng các giải pháp tìm kiếm thất bại với test: ...: binary operator expectednếu có nhiều *.ENDINGtệp trong một thư mục.
Cristian Ciupitu

next(filter(lambda x: x.endswith('.ENDING'), filenames))cũng có thể được viết bằng cách hiểu máy phát điện tức là next(x for x in filenames if x.endswith('.ENDING')).
Cristian Ciupitu

@CristianCiupitu: Sự thật: lệnh find bị hack và chưa thực sự được kiểm tra đầy đủ. Hiểu máy phát điện - vâng đó là một cách hay khác để làm điều đó.
MikeyB

1
Tôi nghĩ rằng một giải pháp thậm chí còn đẹp hơn sẽ được sử dụng if not any(x.endswith('.ENDING') for x in filenames)dựa trên thực tế là bất kỳ lợi nhuận nào Falsecho một lần lặp trống.
Cristian Ciupitu

3

Shell mở rộng *, nhưng trong trường hợp của bạn không có shell liên quan, chỉ có lệnh kiểm tra được thực thi bởi find . Do đó, tập tin có sự tồn tại của nó được kiểm tra, được đặt tên theo nghĩa đen *.ENDING.

Thay vào đó, bạn nên sử dụng một cái gì đó như thế này:

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

Điều này sẽ dẫn đến việc mở rộng sh*.ENDING khi thử nghiệm được thực hiện.

Nguồn: tìm globalbing trên UX.SE


Không hoạt động. Tôi nhận được lỗi sau: sh: -c: line 0: syntax error near unexpected token ('`. Tên thư mục của tôi có định dạng' xyz (dfdf) '. Thực tế nó là một thư viện tầm cỡ.
tre

1
Khi tôi thử nó, tôi nhận được sh: line 0: test: foo1/bar.ENDING: binary operator expectedthư mục chứa một tập tin có phần kết thúc ENDING.
Jenny D

Điều này dường như hoạt động với tôi với tên tập tin a.ENDING đơn giản
user9517

Tôi có cấu trúc thư mục kiểm tra sau: test-> test (test) -> test.ending Sau khi sử dụng mã này, tôi nhận được sh: -c: line 0: syntax error near unexpected token ('sh: -c: line 0:' test -e test (test) / *. End '. / test (test) `. Nhưng khi tôi thay đổi .ending thành .xyz tôi cũng nhận được kết quả tương tự. Điều này là do tôi có các ký tự như tên thư mục, phải không? Làm cách nào tôi có thể sửa nó?
tre

3
@blyn Tôi sẽ từ bỏ các tiện ích shell và tìm kiếm một giải pháp khác vào thời điểm này.
dùng9517

2

Lấy cảm hứng từ câu trả lời của Dennis NolteMikeyB , tôi đã đưa ra giải pháp này:

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

Nó hoạt động dựa trên thực tế là

nếu tùy chọn shell failglob được đặt và không tìm thấy kết quả khớp nào, thông báo lỗi sẽ được in và lệnh không được thực thi.

Nhân tiện, đó là lý do tại sao stderr được chuyển hướng đến /dev/null.


1

Tôi sẽ làm điều đó trong perl cá nhân

#!/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, "." );

Nên làm thủ thuật (hoạt động trên trường hợp thử nghiệm rất đơn giản của tôi).


0

Đây là một tìm thấy một lót.

find ./ -type d ! -regex '.*.ENDING$' -printf "%h\n" | sort -u

Chỉnh sửa : Rất tiếc, cũng không hoạt động.


Nó không hoạt động vì bạn đang kiểm tra tên của các thư mục, không phải các tệp bên trong chúng.
Cristian Ciupitu

Tôi đã thử lại lần nữa. Thật tệ
Matthew Ife

0
find . -type d '!' -exec sh -c 'ls -1 "{}"|egrep -q "*ENDING$"' ';' -print
  • q trong egrep là cho yên tĩnh

  • Với egrepbạn có thể trao đổi regex mà bạn cần

  • ls -1 "{}" xuất tên tệp từ lệnh find

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.