Dosyanın dizinine gitmek için "find" komutunu nasıl kullanabilirim?


11

Bir dosyayı bulmak ve ardından onu içeren dizini girmek istiyorum. Denedim find /media/storage -name "Fedora" | xargs cdama tabii ki is not a directoryhata.

Üst dizinine bir satır komutuyla nasıl girebilirim?


1
Ve birden fazla konumdan birden fazla dosya varsa ne olur?
Sergiy Kolodyazhnyy

@Serg Fedora * .iso dosyasını arıyorum ve sadece bir tane olduğunu biliyorum. Eğer bir tane varsa o zaman ilk direcotry girecekti, sanırım
Hrvoje T

Bash ile shopt -s globstar, yapabilirsin cd /media/storage/**/Fedora, ama bu ilk maçta glob'u değerlendirmeyi bırakmaz (bu yüzden steeldriver'ın çözümünden daha yavaştır. Etkileşimli kullanım için normalde yaptığım şey fare için ulaşmak ve dizin adını kopyalamak / yapıştırmak, (ve alt + backspace, istemediğim sondaki yol bileşenlerini çıkarmak için gerektiği gibi), ancak bunu çok yaparsanız bir kabuk işlevi yapmaya değer olabilir sanırım.
Peter Cordes

1
BTW, xargs cdmuhtemelen çalışamaz. cdyalnızca bir kabuk yerleşimi olarak çalışabilir, çünkü kabuğun kendisini değiştirmek zorundadır. Bir xargsçocuk sürecinin bunu yapmasının bir yolu yoktur . "Elbette" ile kastettiğiniz şeyse IDK veya findyazdırma yolunda, kullanmadığınızdan beri xargs ile ayrılmış boşluklar varsa -d \n. Veya find -exec {} \;.
Peter Cordes

not: böyle çalışamazsınız cd. cdyerleşik bir bash, eğer cdayrı bir komut olsaydı, o zaman (kendi) dir değiştirir ve sonra çıkar (sizi kabuğa geri döndürür, daha önce olduğu gibi aynı durumda, dir değişikliği yok).
ctrl-alt-delor

Yanıtlar:


14

En azından GNU'nuz varsa , dizini almak için findkullanabilirsiniz-printf '%h'

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

Yani muhtemelen yapabilirsin

cd "$(find /media/storage -name "Fedora" -printf '%h' -quit)"

-quitBirden fazla argüman önleyecek cdbirden fazla dosya ile eşleşen durumda.


1
-quitmutlaka desteklenmez. NetBSD'de denir -exit, bkz. Unix.stackexchange.com/a/62883/117599
phk

2
Printf yoksa bunun yerine -exec dirname yapabilir misiniz?
Guy

@ İyi fikir evet, aynı zamanda çalışması gerektiği gibi geliyor
steeldriver

6

Steeldriver'ın çözümüne benzer ancak aşağıdakilerle kombinasyon halinde -execdir( GNU'larfind veya FreeBSD'ler gibi destekliyorsa find) pwd:

cd "$(find /media/storage -name "Fedora" -execdir pwd \; -quit)"

-quityalnızca tek bir sonuç olması ve tüm dizinin taranmasının sorun olmaması durumunda isteğe bağlıdır. NetBSD'de -exitve OpenBSD'de mevcut değildir.


Peki ne \;için?
Hrvoje T

1
@HrvojeT Komutun yürütülmesi için parametrelerin sonunu -execanlatır find. Ama pwdburada parametre olmadan aramak istediğimizden , \;hemen arkasından koyuyoruz .
phk

Herhangi var mıdır finduygulamalar bu destek execdir değil -printf %h? Bana pek benzemiyor. Maalesef POSIX için hiçbiri gerekli değildir: /
Peter Cordes

1
@PeterCordes FreeBSD's find: freebsd.org/cgi/man.cgi?find%281%29 (Sadece bir FreeBSD 11 kurulumunda onaylandı.)
phk

@PeterCordes NetBSD ( netbsd.gw.com/cgi-bin/man-cgi?find++NetBSD-current ) ve OpenBSD ( man.openbsd.org/OpenBSD-current/man1/find.1 ) için aynıdır . Sonuncusu desteklemiyor -quit/ hiç desteklemiyor -exit.
phk

5

Bulduğu dizinde yeni bir kabuk çalıştırmayı bulmayı yapabilirsiniz.

exec find /media/storage -name "Fedora" -execdir "$SHELL" \;

, bundan sonra geçerli dizin içinde Fedora adında bir dosya bulunan dizin olacaktır. ;)

Açıkçası bu sadece etkileşimli komutlar yazıyorsanız ne istediğinizi andırıyor.


4

İle zsh:

cd /media/storage/**/Fedora([1]:h)

için cdadlı bir dosya içeren ilk (alfabetik sırayla) dizine Fedora.

  • **: herhangi bir dizin seviyesi (gizli dirs varsayılan olarak atlanır, Ddahil etmek glob niteleyici kullanın)
  • [1]: sadece ilk
  • :h: head modifier: dizin adını alır.

Aksine cd "$(find ...)", dizin adı yeni satır karakteri ile biterse de çalışır. Başka bir avantaj, eşleşen bir dizin olmadığında (çoğu kabukta sessizce hiçbir şey yapmazken) eşleşme hatası mesajı cd ""almanızdır.

Bir dezavantajı, /media/storagegeri dönmeden önce hepsini tarayacak olmasıdır .


Bash'da, cdbirden çok argümanla birlikte ilk argümana yine de bakar, bu nedenle yolda boşluk yoksa cd $(dirname /media/storage/**/Fedora)(ile shopt -s globstar) çalışır . Düzgün alıntı almak için ben bir bash dizisi en kolay olduğunu düşünüyorum: target=(/media/storage/**/Fedora); cd "${target%/*}". Ancak bu noktada, etkileşimli olarak ortaya çıkmak yerine bulma çıktısını kopyalamak / yapıştırmak için fareyi kullanmak daha hızlı olurdu.
Peter Cordes

2
@PeterCordes, birçok dirnameuygulama birden fazla argümanı kabul etmeyecektir. Boşluk olmadığını , şu anda herhangi bir karakter $IFS(varsayılan olarak boşluk, sekme ve yeni satır) ve joker karakterler olduğunu unutmayın. İster o Not bash'ın cdbirden fazla argüman kabul edecek o (derlendi bağlıdır CD_COMPLAINSiçinde config-top.h). Gelecekteki sürümlerinin bashsonunda zsh gibi iki arg özelliğini de uygulayacağı düşünülebilir.
Stéphane Chazelas

Teşekkürler. Sadece GNU coreutils dirname manpage'e baktım. Dirname sürümü zaten korkunç; Sadece çalıştığı takdirde etkileşimli olarak deneyebileceğiniz bir şey olarak bahsettim. Dizi tabanlı sürümüm bu sorunlardan hiçbirine sahip değildir, çünkü "${target%*/}"yalnızca ilk dizi öğesine ( /Fedorasoyulmuş olarak) genişler . Ben bu sürüm yol adındaki olası karakterlere karşı tamamen sağlam olduğunu düşünüyorum.
Peter Cordes
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.