ค้นหาไดเรกทอรีที่ไฟล์ที่มีจุดสิ้นสุดเฉพาะหายไป


10

ฉันต้องการที่จะแสดงไดเรกทอรีทั้งหมดที่ไม่ได้มีไฟล์ที่มีไฟล์เฉพาะที่สิ้นสุด ดังนั้นฉันพยายามใช้รหัสต่อไปนี้:

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

ในตัวอย่างนี้ฉันต้องการที่จะแสดงไดเรกทอรีทั้งหมดที่ไม่ได้มีไฟล์ที่มีตอนจบ.ENDINGแต่มันไม่ทำงาน

ความผิดพลาดของฉันอยู่ที่ไหน


นี่ไม่ใช่ของลิสต์ไดเรกทอรีที่ไม่ได้มีไฟล์ซ้ำเพราะคำถามนั้นไม่ได้จัดการกับไวด์การ์ด
Cristian Ciupitu

คำตอบ:


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)
Cristian Ciupitu

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

next(filter(lambda x: x.endswith('.ENDING'), filenames))next(x for x in filenames if x.endswith('.ENDING'))อาจจะมีการเขียนโดยใช้เครื่องกำเนิดไฟฟ้าเข้าใจคือ
Cristian Ciupitu

@CristianCiupitu: Truth: คำสั่ง find แฮ็กและไม่ผ่านการทดสอบอย่างเต็มที่ ความเข้าใจของตัวสร้าง - ใช่นั่นเป็นอีกวิธีที่ดีที่จะทำ
MikeyB

1
ฉันคิดว่าวิธีการแก้ปัญหาที่ดีกว่าจะใช้if not any(x.endswith('.ENDING') for x in filenames)ตามความจริงที่ว่าผลตอบแทนใด ๆFalseสำหรับ iterable ว่างเปล่า
Cristian Ciupitu

3

เปลือกขยาย*แต่ในกรณีของคุณมีเปลือกไม่เกี่ยวข้องเพียงการทดสอบคำสั่งดำเนินการโดยหา *.ENDINGดังนั้นไฟล์ที่มีการดำรงอยู่ได้รับการทดสอบเป็นชื่อตัวอักษร

แต่คุณควรใช้สิ่งนี้:

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

ซึ่งจะส่งผลในการดวลจุดโทษขยายตัว*.ENDINGเมื่อทดสอบจะถูกดำเนินการ

แหล่งที่มา: ค้นหา globbing บน UX.SE


ไม่ทำงาน, ไม่เป็นผล. ฉันได้รับข้อผิดพลาดดังต่อไปนี้: sh: -c: line 0: syntax error near unexpected token ('`. ชื่อไดเรกทอรีของฉันมีรูปแบบ' xyz (dfdf) 'อันที่จริงมันเป็นห้องสมุดที่มีความสามารถ
Bamboo

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: บรรทัด 0:' test -e test (test) / *. ลงท้าย ' / test (test) `แต่เมื่อฉันเปลี่ยน. ถึง. xyz ฉันจะได้รับผลลัพธ์เดียวกันนั่นเป็นเพราะฉันมี bracts เป็นชื่อไดเรกทอรีใช่ไหมฉันจะแก้ไขได้อย่างไร
Bamboo

3
@ ไม้ไผ่ฉันจะยอมแพ้กับโปรแกรมอรรถประโยชน์ของเชลล์และค้นหาวิธีแก้ไขปัญหาที่แตกต่างกัน ณ จุดนี้
user9517

2

แรงบันดาลใจจากเดนนิสโนลเต้ของและMikeyB ของคำตอบฉันมาด้วยวิธีนี้

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

มันทำงานตามความจริงที่ว่า

หากตั้งค่าอ็อพชันfailglob shell และไม่พบข้อมูลที่ตรงกันข้อความแสดงข้อผิดพลาดจะถูกพิมพ์และคำสั่งจะไม่ถูกดำเนินการ

โดยวิธีการที่ว่าทำไมstderr/dev/nullถูกเปลี่ยนเส้นทางไปยัง


1

ฉันจะทำมันด้วยตัวเอง

#!/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 ! -regex '.*.ENDING$' -printf "%h\n" | sort -u

แก้ไข : อ๊ะไม่ทำงานเหมือนกัน


มันไม่ทำงานเพราะคุณกำลังทดสอบชื่อของไดเรกทอรีไม่ใช่ไฟล์ที่อยู่ในนั้น
Cristian Ciupitu

ฉันลองอีกครั้ง ไม่ดี
Matthew Ife

0
find . -type d '!' -exec sh -c 'ls -1 "{}"|egrep -q "*ENDING$"' ';' -print
  • q ใน egrep สำหรับความเงียบ

  • ด้วยegrepคุณสามารถสลับ regex ที่คุณต้องการ

  • ls -1 "{}" เอาต์พุตชื่อไฟล์จากคำสั่ง find

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.