รายการไดเรกทอรีทั้งหมดที่ไม่มีไฟล์ที่มีชื่อไฟล์ที่กำหนดไว้ภายใน


12

ฉันจะไปยังรายการไดเรกทอรีทั้งหมดที่ไม่มีไฟล์ที่มีชื่อไฟล์ที่กำหนดไว้ภายในได้อย่างไร? เช่นได้รับต้นไม้ต้นนี้

/
  /a
     README
     file001
     file002
  /b
     README
     file001
  /c
     file003

ฉันต้องการที่จะแสดงรายการไดเรกทอรีที่ไม่ได้ตั้งชื่อไฟล์เป็นในกรณีนี้มันจะเป็นไดเรกทอรีREADME /cฉันจะทำอย่างไร ฉันไม่สามารถคิดใด ๆ findไวยากรณ์ใช้เช่น


ความอัปยศโอ้ความอัปยศที่คุณไม่ได้ค้นหา: askubuntu.com/questions/196960/…
slm

ฉันไม่ได้คิดถึงคำหลักที่ถูกต้องเมื่อทำการค้นหา
Renan

2
ฉันแค่หน้าอกของคุณสับ ฉันเคยไปที่นั่นหลายครั้งแล้วซึ่งฉันไม่สามารถนึกถึงคำที่ถูกต้องในการค้นหาสิ่งที่ 8-)
slm

คำตอบ:


5

สมมติว่ามีfindการนำไปใช้อย่าง GNU findที่ยอมรับการ{}ฝังตัวในอาร์กิวเมนต์เพื่อ-exec:

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

ตัวอย่าง

นี่ไดเรกทอรี 1/1 ถึง 5/5 มี README, dirs อื่นว่างเปล่า

$ tree 
.
|-- 1
|   `-- 1
|       `-- README
|-- 10
|   `-- 10
|-- 2
|   `-- 2
|       `-- README
|-- 3
|   `-- 3
|       `-- README
|-- 4
|   `-- 4
|       `-- README
|-- 5
|   `-- 5
|       `-- README
|-- 6
|   `-- 6
|-- 7
|   `-- 7
|-- 8
|   `-- 8
`-- 9
    `-- 9

ตอนนี้เมื่อเรารันเวอร์ชันfindคำสั่งของเรา:

$ find . -type d \! -exec test -e '{}/README' \; -print
.
./10
./10/10
./7
./7/7
./9
./9/9
./6
./6/6
./5
./8
./8/8
./4
./1
./3
./2

อ้างอิง


วิธีแก้ไขคำสั่งเพื่อค้นหาไดเรกทอรีย่อยที่ไม่มีนามสกุลไฟล์เฉพาะ (พูด * .txt) การแก้ไข README ด้วย * .txt ดูเหมือนจะใช้งานไม่ได้
WanderingMind

@WanderingMind - หากคุณมีคำถามใหม่โปรดถามว่าเป็นคำถามใหม่ในเว็บไซต์ ;-)
slm

3

คุณสามารถใช้-execตัวเลือกในfindการตรวจสอบไฟล์แล้วพิมพ์ผลลัพธ์ทั้งหมดที่การตรวจสอบล้มเหลว

find /path/to/base -mindepth 1 -maxdepth 1 -type d -exec test -e {}/README \; -o -print

3

findไม่จำเป็นต้อง เพียงใช้เปลือก:

for d in */; do [ -f "$d"README ] || printf '%s\n' "$d"; done
c/

หากคุณต้องการให้มันเกิดซ้ำคุณสามารถใช้ (สำหรับbash, zshสามารถทำได้โดยค่าเริ่มต้น, ใช้set -o globstarในksh93):

shopt -s globstar
for d in **/; do [ -f "$d"README ] || printf '%s\n' "$d"; done

(โปรดทราบว่าค่าเริ่มต้นจะยกเว้นไฟล์จุด)


2

ด้วยzshและqualifier qualifier ( eสตริง ):

print -rl -- *(/e_'[[ ! -f $REPLY/README ]]'_)

หรือ

print -rl -- *(/^e_'[[ -f $REPLY/README ]]'_)

เพิ่มDเพื่อรวมไดเรกทอรีที่ซ่อนอยู่:

print -rl -- *(D/e_'[[ ! -f $REPLY/README ]]'_)

/เลือกเฉพาะไดเรกทอรีและe_'[[ ! -f $REPLY/README ]]'_เลือกเพิ่มเติมเพียงชื่อไดเรกทอรีที่รหัสเปลือกระหว่างคำพูดที่ให้ผลตอบแทนtrueที่เป็นชื่อของแต่ละ directory ( $REPLY) ที่ glob *(/)ขยายเพื่อจะทำงานและช่วยให้ชื่อของไดเรกทอรีถ้าผลที่ได้คือ[[ ! -f $REPLY/README ]] รูปแบบที่สองใช้คัดเลือก glob เดียวกันเมื่อตะกี้ ( แต่เวลานี้การแสดงออกเงื่อนไขไม่ได้เมื่อตะกี้: ) true
^e_'.....'_[[ -f $REPLY/README ]]


ด้านบนจะส่งคืนชื่อไดเรกทอรีในไดเรกทอรีปัจจุบันเท่านั้น
หากคุณต้องการค้นหาแบบเรียกซ้ำ (อีกครั้งเพื่อรวมไดเรกทอรีที่ซ่อนอยู่ให้เพิ่มตัวระบุD):

print -rl ./**/*(/e_'[[ ! -f $REPLY/README ]]'_)

2

แบบพกพาคุณสามารถทำ:

find . -type d -exec sh -c '
  for dir do
    [ -f "$dir/README" ] || printf "%s\n" "$dir"
  done' sh '{}' +

[ -f file ]ทดสอบว่ามีไฟล์อยู่ และได้รับการยืนยันว่าเป็นไฟล์ปกติ (หลังจากการแก้ปัญหา symlink)

หากคุณต้องการทดสอบว่ามีอยู่เท่านั้น (เป็นรายการในไดเรกทอรีนั้น) ไม่ว่าจะเป็นประเภทใดคุณจำเป็นต้อง: [ -e file ] || [ -L file ]แม้ว่าโปรดทราบว่าคุณต้องได้รับอนุญาตจากการค้นหาในไดเรกทอรีเพื่อทำการทดสอบเหล่านั้น คุณอาจต้องการเพิ่ม[ -x "$dir" ]การทดสอบลงในบัญชีสำหรับกรณีเหล่านี้เช่น:

find . -type d -exec sh -c '
  for dir do
    if [ -x "$dir" ]; then
      [ -f "$dir/README" ] || printf "%s\n" "$dir"
    else
      printf >&2 "Cannot tell for \"%s\"\n" "$dir"
    fi
  done' sh '{}' +

หรือเพื่อหลีกเลี่ยงสภาพการแข่งขันด้วยzsh:

find . -type d -exec zsh -c '
  zmodload zsh/system
  for dir do
    ERRNO=0
    if [ ! -f "$dir/README" ]; then
      if [ "$errnos[ERRNO]" = ENOENT ]; then
        printf "%s\n" "$dir"
      else
        syserror -p "ERROR: $dir/README: "
      fi
    fi
  done' zsh '{}' +

ดูเพิ่มเติมฉันจะทราบได้อย่างไรว่าไฟล์ปกติไม่มีอยู่ใน Bash บนดังนั้น

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