İçinde belirli bir dosya adı olan bir dosya OLMAYAN tüm dizinleri listele


12

Nasıl mı tüm dizinleri listeleme girecek değil , belirli bir dosya adı içeriden bir dosya var mı? örneğin bu ağaç verildi

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

Adında bir dosya olmayan dizinleri listelemek istiyorum README, bu durumda dizin olur /c. Bunu nasıl yaparım? Örneğin kullanarak herhangi bir sözdizimi düşünemiyorum find.


Utanç oh utanç bile aramadı
slm

Muhtemelen arama yaparken doğru anahtar kelimeleri düşünmedim.
Renan

2
Ben sadece pirzolalarını bust'in. 8-) Bir şeyi aramak için doğru kelimeyi düşünemediğim birçok kez orada bulundum.
slm

Yanıtlar:


5

findGNU gibi bir argümana katıştırılmış bir uygulamayı findkabul {}ederek -exec:

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

Misal

Burada 1/1 - 5/5 dizinleri bir README'ye sahiptir, diğer dizinler boştur.

$ 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

Şimdi findkomutumuzun bu sürümünü çalıştırdığımızda :

$ 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

Referanslar


Belirli bir dosya uzantısına sahip olmayan alt dizinleri aramak için komut nasıl değiştirilir (diyelim * .txt). * .Txt ile README'yi değiştirmek işe yaramıyor
WanderingMind

@WanderingMind - yeni bir sorunuz varsa lütfen sitede yeni bir soru olarak sorun ;-)
slm

3

Dosyayı denetleme -execseçeneğini kullanabilir findve ardından denetimin başarısız olduğu tüm sonuçları yazdırabilirsiniz.

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

3

Gerek yok find. Sadece kabuğu kullanın:

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

Eğer özyinelemeli olmasını gerekiyorsa (için kullanabileceğiniz bash, zshvarsayılan kullanım yapabilirsiniz set -o globstariçinde ksh93):

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

(nokta dosyalarının varsayılan olarak hariç tutulduğunu unutmayın).


2

İle zshve glob niteleyicileri ( edize ):

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

veya

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

Dgizli dizinleri eklemek için ekle :

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

/yalnızca dizinleri seçer ve e_'[[ ! -f $REPLY/README ]]'_yalnızca tırnak işaretleri arasındaki kabuk kodunun döndürdüğü dizin adlarını true, yani $REPLYglob'un *(/)genişlediği her dizin adı ( ) için çalışır [[ ! -f $REPLY/README ]]ve sonuçsa dizinin adını korur true.
İkinci form ^e_'.....'_, reddedilen aynı glob niteleyicisini kullanır (ancak bu kez koşullu ifade reddedilmez:) [[ -f $REPLY/README ]].


Yukarıdakiler yalnızca geçerli dizindeki dizin adlarını döndürür.
Yinelemeli olarak arama yapmak istiyorsanız (tekrar, gizli dizinleri dahil etmek için Dniteleyiciyi ekleyin ):

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

2

Portably, şunları yapabilirsiniz:

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

[ -f file ]Dosya eğer testler var ve onaylanır (sembolik link çözünürlükte sonra) düzenli dosyasını olmak.

Türüne bakılmaksızın, yalnızca var olduğunu (bu dizindeki bir girdi olarak) test etmek isterseniz, şunlara ihtiyacınız olacaktır: [ -e file ] || [ -L file ]ancak bu testleri gerçekleştirmek için dizinde arama iznine ihtiyacınız olduğunu unutmayın. Bu [ -x "$dir" ]gibi durumları hesaba katmak için bazı testler eklemek isteyebilirsiniz :

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 '{}' +

Veya yarış koşullarından kaçınmak için 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 '{}' +

Ayrıca bkz . Bash'te normal bir dosyanın bulunmadığını nasıl anlarım? bu yüzden.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.