Kaynak içeren tüm dizinler nasıl bulunur?

Birkaç dizini olan bir projem var (tümü önceden bilinmemiş). Kaynakları içeren tüm dizinleri bulmak için bir komut vermek istiyorum. gibi bir şey bulur. -name "* .cpp" bu sadece onları içeren dizinlerin listesini isterken bana kaynakların bir listesini verecektir. Proje yapısı önceden bilinmemektedir, bazı kaynaklar X dizininde, bazıları ise X/Y alt dizininde bulunabilir. Kaynakları içeren tüm dizinlerin listesini basacak komut ne olacaktır?

3
Neden soruyorsun? Bu proje nedir? Genel bir çözüm ister misiniz? Neden proje kaynağı sürüm kontrol deposunu kullanamıyorsunuz? Lütfen geliştirmek için sorunuzu düzenleyin!
katma yazar Basile Starynkevitch, kaynak
Bir yana: Cevap veren herkese cevap vermek için zaman harcadığınızı görmek güzel.
katma yazar mklement0, kaynak

6 cevap

find . -name "*.cpp" -exec dirname {} \; | sort -u

(A) GNU find 'a veya BSD find ' in son bir sürümüne sahipseniz ve (b) dirname 'nin son sürümüne sahipseniz (örneğin GNU coreutils 8.21 veya FreeBSD 10, ancak OSX 10.10 değil , daha sonra, daha yüksek verimlilik için, kullan (Hat ucu: Jochen ve mklement0):

find . -name "*.cpp" -exec dirname {} + | sort -u
5
katma
Doğru anladın
katma yazar e271p314, kaynak
@ John1024: (GNU coreutils) 8.13 dirname sürümü (örneğin, Debian 3.2'de) desteklemiyor, ancak (GNU coreutils) 8.21 (örneğin, Ubuntu 14.04 ve Fedora 20'de) yok . Benzer şekilde, BSD dünyasında, OSX 10.10 sürümü birden fazla argümanı desteklemiyor, oysa FreeBSD 10 sürümü destekliyor .
katma yazar mklement0, kaynak
Benim için zevkti @ John1024. Ben burada sadece dirname sürümünün değişken olduğunu düşünüyorum, + -exec ile bitene kadar, find sürümünün de değişmediğini düşünüyorum./code> bir POSIX uyumlu bir özelliktir .
katma yazar mklement0, kaynak
@Jochen Teşekkürler! Ayrıca, ilginç öneri. Birden çok argüman işleyen ne dirname kullanıyorsunuz? Mine (debian stabil) yapmaz.
katma yazar John1024, kaynak
@ mklement0 ve Jochen, teşekkürler! Cevap, + seçeneği ve sürüm bilgisi ile güncellendi.
katma yazar John1024, kaynak
Neden kendim düşünmedim? :) Eğer GNU bulursanız, çağrıları kolayca + kullanarak dirname 'ye kaydedebilirsiniz; bulun. -adı \ *. cpp -exec dirname '{}' + | sort -u
katma yazar Jochen, kaynak

John1024's answer is elegant and fast, IF your version of dirname supports multiple arguments and you can invoke it with -exec dirname {} +.

Aksi takdirde, -exec dirname {} \; ile, oldukça yavaş olan her bir giriş dosya adı için bir alt işlem çatallanır.

Eğer:

  • dirname adınız birden fazla argümanı desteklemiyor
  • ve performans sorunları
  • ve bash 4 veya daha üstünü kullanıyorsunuz

aşağıdaki çözümü göz önünde bulundurun:

shopt -s globstar; printf '%s\n' ./**/*.cpp | sed 's|/[^/]*$||' | sort -u
  • shopt -s globstar activates support for cross-directory pathname expansion (globbing)
  • ./**/**.cpp then matches .cpp files anywhere in the current directory's subtree

    • Note that the glob intentionally starts with ./, so that the sed command below also properly reports the top-level directory itself, should it contain matching files.
  • sed 's|/[^/]*$||' effectively performs the same operation as dirname, but on all input lines with a single invocation of sed.

  • sort -u sorts the result and outputs only unique directory names.
3
katma
Globstar, az kullanılan bir özelliktir: + 1.
katma yazar John1024, kaynak
find . -name "*.cpp" | while read f; do dirname "$f" ; done | sort -u

ihtiyacın olanı yapmalısın

1
katma
Doğru yaptın ama @ John1024 daha kısa ve temiz bir komut yazdı
katma yazar e271p314, kaynak
evet gerçekten de yaptı! Benden +1 ...
katma yazar leu, kaynak
find . -name '*.cpp' | sed -e 's/\/[^/]*$//' | sort | uniq
1
katma
Doğru yaptın ama @ John1024 daha kısa ve temiz bir komut yazdı
katma yazar e271p314, kaynak

Boş olmayan dizinleri bulmak için:

$ find. \! -topty -type d

İçinde sadece belirli dosya tiplerine sahip dizinler için şöyle bir şey kullanırdım:

bulun. -name \ *. cpp | satır okunurken; "$ {line}" dirname yap; bitti | sort -u

Bu, tüm * .cpp dosyalarını bulur ve her dosya adına dirname 'i çağırır. Sonuç sıralanır ve benzersiz yapılır. Bunu, her * .cpp dosyası için yeni bir işlem oluşturmasını gerektirmeyen kabuk yerleşiklerini kullanarak yapmanın kesinlikle daha hızlı yolları var. Ancak bu muhtemelen çoğu proje için önemli olmamalıdır.

1
katma
Kabuk yerleşiklerini kullanmak, find seçeneğiyle bir seçenek değildir, ancak bash 4+ kullanıyorsanız, shopt -s globstar ile yol adı genişletmesini kullanarak daha hızlı bir çözüm mümkündür.
katma yazar mklement0, kaynak

Kaynak dosyanın ne olduğunu tanımlamanız gerekir.

Bazı C veya C ++ dosyalarının genge< olduğuna dikkat edin (örneğin, bizon veya yacc , geçici awk veya python veya kabuk komut dosyaları ile belirli üreticilere göre proje vb.) ve içerdiği bazı C veya C ++ dosyalarının .h veya .cc olarak adlandırılmadıklarını ( X-makroları ). GCC içinde önemli miktarda dosya oluşturulur (örn. * .md makine açıklaması) otantik kaynak dosyalar olan dosyalar)

Çoğu büyük yazılım projesi (örneğin, milyonlarca satır C ++ veya C kodu) bir yerlerde bazı C veya C ++ kod üreteçleri kullanıyor veya kullanıyor.

Özgür yazılım dünyasında, bir kaynak kod, geliştiricinin üzerinde çalıştığı kodun tercih edilen şeklidir .

Kaynak kodun bir dosyaya bile oturmayabileceğine dikkat edin; bir veri tabanında, bazı yığın görüntülerinde, örn. geliştirici çalışmak için belirli bir programla etkileşime giriyorsa. (1980'lerin Smalltalk makinelerini veya 1980’deki INRIA’da Mentor yapısal editörünü unutmayın). Başka bir örnek olarak, J.Pitrat’ın CAIA sistemi tamamen C koduna sahip kendini üretti. Ayrıca Scheme48 içine de bakın

Belki de (sadece yaklaşık sezgisel), .h veya .cc veya .cpp veya .cxx veya GENELATED FILE içermeyen .def veya .inc veya .tcc kodlarını ekleyin./code> words (genellikle bazı yorumlar içinde).

Oluşturulan dosyaların ne olduğunu anlamak için derleme prosedürüne dalmalısınız ( Makefile , CMake * , Makefile.am ile autoconf vb vb ...). Oluşturulan C ++ dosyalarını algılamanın veya tahmin etmenin aptalca bir yolu yoktur ; Böylece algılamalarını güvenilir bir şekilde otomatikleştiremezsiniz.

Sonunda, bootstrapped dilleri sıklıkla bazı oluşturulan dosyaları içeren bir (sürüm kontrolü) deposuna sahiptir. Ocaml’ın önyükleme/ alt dizine ve MELT 'de eriyik/üretilen/ dizini var (MELT’yi C ++ biçiminde yeniden oluşturmak için gereken C ++ dosyalarını içeren) * .melt kaynak kod dosyalarından).

I would suggest to use the project version control repository and get the non-empty directories there. Details depend upon the version control tool (e.g. git, or svn, or hg, etc...). You should use some version control (or revision control) tool. I recommend git

0
katma
O zaman son paragrafımın alakalı olduğuna inanıyorum. OP, bir sürüm kontrol aracı kullanmalıdır.
katma yazar Basile Starynkevitch, kaynak
İyi bilgi, ancak bunu çok fazla düşünüyor olabilirsiniz: OP'nin [C ++] kaynak dosyalarını tespit etmek için genel bir yol aradığını sanmıyorum. Kabul ettikleri cevap, ihtiyaç duyulan her şeyin, belirli ilgi eklerine sahip dosyaları içeren dizinleri bulmanın bir yolu olduğunu göstermektedir.
katma yazar mklement0, kaynak