Tüm "izin reddedildi" iletilerini "bul" öğesinden nasıl hariç tutabilirim?


794

Tüm izin reddedilen iletileri gizlemem gerekiyor :

find . > files_and_folders

Böyle bir mesaj ortaya çıktığında denemeler yapıyorum. Ortaya çıkmadığı tüm klasörleri ve dosyaları toplamam gerekiyor.

İzin düzeylerini files_and_foldersdosyaya yönlendirmek mümkün mü ?

Hataları aynı anda nasıl gizleyebilirim?

Yanıtlar:


259

Not:
* Bu cevap muhtemelen kullanım durumunun gerektirdiğinden daha derine iner ve find 2>/dev/nullbirçok durumda yeterince iyi olabilir. Platformlar arası bir bakış açısı ve bazı ileri kabuk tekniklerinin, mümkün olduğu kadar sağlam bir çözüm bulmak amacıyla tartışılması ilgi çekebilir, ancak korunan davalar büyük ölçüde varsayımsal olabilir.
* Sisteminiz yerelleştirilmiş hata mesajlarını gösterecek şekilde yapılandırılmışsa , İngilizce mesajların bildirildiğinden emin olmak için findaşağıdaki çağrılara LC_ALL=C( LC_ALL=C find ...) önek koyun , böylece amaçlanan şekilde çalışır. Bununla beraber her zaman herhangi bir hata iletileri do görüntülenen olsun sonra İngilizce olması yanı olacaktır. grep -v 'Permission denied'

Sizin ise kabuk bashveyazsh , orada makul basit olurken sağlam bir çözüm kullanılarak, sadece POSIX uyumlu findözelliklere ; ise bashPOSIX'e parçası değil kendisi en modern Unix platformlarında bu çözüm yaygın taşınabilir hale onunla gelir:

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

Not: Genel komut, içerideki komutun bitmesini beklemediğinden , bazı grepçıktılarının tamamlandıktan sonra gelmesi olasılığı düşüktür . Gelen , sen ekleyerek bunu engelleyebilirsiniz komutuna.find>(...)bash| cat

  • >(...)Bir (nadiren kullanılır) 'dir çıkış süreci ikamesi bu durumda (çıkış yönlendirme sağlar, stderr çıkışı ( 2>komut içinin stdin'e) >(...).
    ilaveten bashve zsh, kshyanı destekler onları prensipte ancak gelen yönlendirme ile bunları birleştirmek için çalışıyor stderr , burada yapıldığı gibi ( 2> >(...)) sessizce göz ardı ediliyor gibi görünmektedir ksh 93u+.

    • grep -v 'Permission denied'filtre üzerinden ( -v) (tüm hatlar findifadeyi içeren komutunun şekilde hataları akım) Permission deniedve stderr'e kalan sinyallerini üretecek ( >&2).

Bu yaklaşım:

  • sağlam : grepyalnızca hata iletilerine (ve potansiyel olarak yanlış pozitiflere yol açan dosya yollarının ve hata iletilerinin bir kombinasyonuna değil) uygulanır ve izin reddedilenler dışındaki hata iletileri stderr'e iletilir.

  • tarafının etkisi ücretsiz : find'ın çıkış kodu korunur: erişime çıkış kodunda sonuçları karşılaşılan dosya sistemi öğelerden en az biri yetersizlik 1(yani hatalar olmadığı konusunda bilgi olmasa da diğer izni reddedildi olanlardan daha (oluştu çok)).


POSIX uyumlu çözümler:

Tamamen POSIX uyumlu çözümlerin ya sınırlamaları vardır ya da ek çalışmalar gerektirir.

Eğer findbireyin çıkışı yakalanan edilecek dosyanın zaten (veya tamamen bastırılmış), sonra gelen boru hattı tabanlı çözüm Jonathan Leffler cevap basit, sağlam ve POSIX uyumludur:

find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2

: Yönlendirmeler sırası önemlidir unutmayın 2>&1gelmelidir ilk .

Bir dosyanın ön tarafındaki stdout çıktısının yakalanması , ardışık düzende açık bir şekilde çalışabilen yalnızca hata mesajlarını boru hattı üzerinden 2>&1göndermeye izin verir .grep

Tek dezavantajı olduğunu genel çıkış kodu olacaktır grepkomutunun değil findvarsa, bu davadan araçlarında 'ın, hiçbir tamamını veya en hatalar sadece izne reddedildi hataları, çıkış kodu olacaktır 1(sinyalizasyon arızası (aksi takdirde) izin reddedilenler dışındaki hatalar) 0- niyetin tam tersi.
Bununla birlikte, findçıkış kodu nadiren kullanılır , çünkü genellikle varolmayan bir yoldan geçmek gibi temel başarısızlığın ötesinde çok az bilgi taşır .
Bununla birlikte, sadece bazılarının bileGiriş yolları sebebiyle izinleri olmaması için erişilemez olma olduğu yansıtılır find(GNU ve BSD hem de 'in çıkış kodu find): bir izin reddedildi hata için oluşması durumunda herhangi bir işlenmiş dosyaların, çıkış kodu olarak ayarlanır 1.

Aşağıdaki varyasyon şunları ele almaktadır:

find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }

Şimdi, çıkış kodu dışında herhangi bir hata olup olmadığını gösterir Permission denied: 1öyleyse, 0aksi takdirde.
Başka bir deyişle: çıkış kodu artık komutun gerçek niyetini yansıtmaktadır: 0Hiç hata yoksa veya yalnızca izin verilmeyen hatalar oluşmazsa success ( ) bildirilir .
Bu, findüstteki çözümde olduğu gibi, çıkış kodunu geçirmekten bile daha iyidir .


gniourf_gniourf yorumlarda (hala POSIX uyumlu) önermektedir sofistike yönlendirmeleri kullanarak bu çözümün genelleme , dosya yolları baskı varsayılan davranışı ile bile çalışır Stdout'a :

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

Kısacası: 3stdout ( 1) ve stderr ( 2) işlevlerini geçici olarak değiştirmek için özel dosya tanımlayıcı kullanılır , böylece hata iletileri yalnızcagrep stdout aracılığıyla iletilebilir .

Bu yönlendirmeler olmadan, hem veriler (dosya yolları) hem de hata iletileri grepstdout aracılığıyla iletilir ve grepdaha sonra hata iletisi Permission denied ile adı ifadeyi içeren bir (varsayımsal) dosya arasında ayrım yapamaz Permission denied.

Bununla birlikte, ilk çözümde olduğu gibi, bildirilen çıkış kodu grep'değil find' olacaktır , ancak yukarıdaki ile aynı düzeltme uygulanabilir.


Mevcut cevaplarla ilgili notlar:

  • Hakkında nota birkaç nokta vardır Michael brux cevabı , find . ! -readable -prune -o -print:

    • GNU gerektirir find; özellikle macOS üzerinde çalışmaz. Tabii ki, sadece GNU ile çalışmak için komuta ihtiyacınız varsa find, bu sizin için bir sorun olmayacaktır.

    • Bazı Permission deniedhatalar hala ortaya çıkabilir : geçerli kullanıcının izni olduğu dizinlerin alt öğeleri find ! -readable -pruneiçin bu tür hataları bildirir , ancak (yürütülebilir) izne sahip değildir. Sebebi dizinin kendisi olmalarındandır olan okunabilir, infaz edilmez ve aşağı inerek girişimi içine bu dizinde sonra hata iletileri tetikler. Bununla birlikte, tipik durum iznin eksik olması içindir.rx-pruner

    • Not: Aşağıdaki nokta, bir felsefe ve / veya belirli bir kullanım durumu meselesidir ve bunun sizin için uygun olmadığına ve komutun ihtiyaçlarınızı tam olarak karşıladığına karar verebilirsiniz, özellikle de sadece yolları yazdırmanız yeterlidir :

      • Eğer siz izin reddedildi hata mesajlarının bir filtrelenmesini conceptualize ayrı sen uygulamak isterler bu görev herhangi find komuta ardından proaktif ters yaklaşımı engelleyen izni reddedildi hataları içine "gürültü" tanıtan gerektirir findkomutu, aynı zamanda tanıtır karmaşıklık ve mantık tuzakları .
      • Örneğin, Michael'ın cevabına en çok oylanan yorum (bu yazıdan itibaren) , aşağıdaki gibi bir filtre ekleyerek komutun nasıl genişletileceğini göstermeye çalışır -name:
        find . ! -readable -prune -o -name '*.txt'
        Ancak, bu , amaçlanan şekilde çalışmaz, çünkü sondaki -printeylem gereklidir ( bu cevapta bir açıklama bulunabilir ). Bu incelikler böcek getirebilir.
  • İlk çözüm Jonathan Leffler cevap , find . 2>/dev/null > files_and_folderskendisinin de ifade ettiği gibi, körü körüne susturan bütün hata mesajlarını (ve o da açıkladığı gibi geçici çözüm, tamamen sağlam hantal ve değil). Pragmatik olarak konuşmak gerekirse , en basit çözümdür , çünkü herhangi bir hatanın ve tüm izinlerle ilgili olacağını varsaymaktan memnun olabilirsiniz.

  • mist cevabı , sudo find . > files_and_folders, özlü ve pragmatik ancak sadece başka bir şey için tedbirsiz olduğu baskı dosya adları güvenlik nedenleriyle,: Eğer olarak çalıştırıyorsunuz çünkü kök kullanıcı, "find bir hata berbat olmak için tüm sistemi sahip riski veya kötü amaçlı bir sürümü veya beklenmedik bir şekilde yazan yanlış bir çağrıyı (normal ayrıcalıklarla çalıştırırsanız gerçekleşmeyebilir) "(sisin üçlü olarak yanıtına yaptığı bir yorumdan ).

  • İçinde 2 solüsyon viraptor cevabı , find . 2>&1 | grep -v 'Permission denied' > some_fileve potansiyel olarak yerine raporlama (nedeniyle boru hattından stdout ve stderr bir karışımını gönderme) yanlış pozitif riskini taşır olmayan çıkış yolları yanında yakalar, onları stderr'e yoluyla -permission reddedildi hataları çıktı dosyasında.


4
Sadece hızlı bir soru: neden bir süreç ikamesini ve sadece bir boru kullanırım: find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?
gniourf_gniourf

2
@ LéoLéopoldHertz 준영: Harici bir dosyaya çıktı almak istemiyorsanız, daha fazla tesisat yapın:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf

2
@ LéoLéopoldHertz 준영: Sadece POSIX uyumlu. Proses ikameleri >(...)Bash'e özgüdür.
gniourf_gniourf

2
Çıkış kodunun korunmasının findvurgulanması ve reklamının yapılması gerektiğinden emin değilim : findçıkış kodu herkesin bildiği gibi işe yaramaz. Burada, muhtemelen sıfırdan farklı olacaktır (ve işe yaramaz şekilde).
gniourf_gniourf

3
POSIX, execute/searchbir dizini 'aramak' (içerilen dosyaların düğümlerini almak) için açıkça dosya modu izni gerektirir . findbunu bir alt dizine inmek için yapar ( readbir dizindeki dosyaları listelemek için izin gerekmesine ek olarak ). Bu bir 'hata' veya 'taşıma hatası' değildir.
wjordan

542

kullanın:

find . 2>/dev/null > files_and_folders

Bu sadece Permission deniedhataları değil elbette tüm hata mesajlarını da gizler .

Bir symlink'te çok fazla atlama gibi izinler değil, diğer olası hataları gerçekten tutmak istiyorsanız, ancak izin reddedilenleri değil, muhtemelen 'izin reddedildi' adı verilen birçok dosyanızın olmadığına dair uçan bir tahminde bulunmanız gerekir. ve dene:

find . 2>&1 | grep -v 'Permission denied' > files_and_folders

Sadece standart hatayı filtrelemek istiyorsanız, daha ayrıntılı yapıyı kullanabilirsiniz:

find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2

I / O yönlendirmesi üzerine findkomuta geçerli: 2>&1 > files_and_folders |. Boru, standart çıktıyı grepkomuta yönlendirir ve önce uygulanır. 2>&1Standart çıkış (boru) ile aynı yere standart hata gönderir. > files_and_foldersBir dosyaya standart çıktıyı (ancak standart değil hatası) gönderir. Net sonuç, standart hataya yazılan mesajların kanaldan gönderilmesi ve normal çıktısının finddosyaya yazılmasıdır. grepStandart çıktı ve son (sen olmasını istediğiniz seçici ve yerel ayar ve O / S bağlı yazım değiştirmeniz gerekebilir nasıl karar verebilir) filtreler>&2hayatta kalan hata mesajlarının (standart çıktıya yazılan) bir kez daha standart hataya gittiği anlamına gelir. Son yönlendirme terminalde isteğe bağlı olarak kabul edilebilir, ancak hata mesajlarının standart hatada görünmesi için bir komut dosyasında kullanmak çok iyi bir fikir olacaktır.

Ne yapmak istediğinize bağlı olarak bu temada sonsuz varyasyonlar var. Bu, herhangi bir Bourne kabuğu türevi (Bash, Korn,…) ve herhangi bir POSIX uyumlu sürümü ile Unix'in herhangi bir varyantı üzerinde çalışacaktır find.

findSisteminizde bulunan belirli bir sürüme uyum sağlamak isterseniz , mevcut alternatif seçenekler olabilir. findÖzellikle GNU'nun diğer sürümlerde bulunmayan sayısız seçeneği vardır - bu seçeneklerden biri için şu anda kabul edilen cevaba bakınız.


9
Eğer benim gibi iseniz, yer eksikliğinin önemli olduğunu unutmayın! 2>/dev/null, boşluksuz!
Nik

20
2>Herhangi bir boşluk olmaksızın tek bir birim; dosya ile dosya adı arasında boşluk olabilir. Benzer şekilde 2>&1(standart hatayı standart çıktıyla aynı yere yönlendiren) veya 2>&-standart hatayı kapatan vb. Gibi diğer yönlendirmelere benzer . Kalan kanlı ayrıntılar için bkz . (Yukarıdaki kod, spesifik olmayan genel POSIX benzeri kabuktur bash.)
Jonathan Leffler

3
Büyük bir P kullanmak zorunda kaldım çünkü terminalimin çıktısı bu olurdu: find. 2> & 1 | grep -v 'İzin reddedildi'
David Doria

4
Bu nasıl kabul edilebilir bir çözüm? 1) TÜM hataları dev / null'a yönlendiriyorsunuz 2) Açık bir hata dizesini filtreliyorsunuz !! Bunlara bağlı olarak ünlü kırılgan ve ya dosya 'izin reddedildi' adlı bir dizinde olsaydı? Hata!
Gunchars

10
Programın çıktısını değiştirmek için hata dizelerini açmaya karşı itiraz ediyorum. Çoğu zaman işe yarayacaktır, ancak basit doğru çözüm değildir (aşağıdaki izinlerle bulabilirsiniz). Size bir örnek vermek gerekirse, bu hata OSX üzerinde çalışmaz çünkü hata "İzin reddedildi". Hata dizesinde küçük çaplı farklılıkların bile olduğu diğer herhangi bir sistem için aynıdır (uluslararasılaşma
kimsede

285

kullanın:

find . ! -readable -prune -o -print

veya daha genel olarak

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • "İzin verilmedi"
  • VE (diğer) hata mesajlarını BASMAYIN
  • VE çıkış durumu 0'ı al ("tüm dosyalar başarıyla işlenir")

Şununla çalışır: find (GNU findutils) 4.4.2. Arka fon:

  • -readableTest okunabilir dosyalar eşleşir. !Test yanlış olduğunda operatörü, true döndürür. Ve ! -readableokunamayan dizinlerle (& dosyalar) eşleşir.
  • -pruneEylem dizinin içine girer etmez.
  • ! -readable -prune şu dile çevrilebilir: dizin okunamıyorsa, bu klasöre girmeyin.
  • -readableTest hesabı erişim denetim listeleri ve diğer izinler eserler dikkate alır -permtesti yoksaydıklarınız.

Daha fazla ayrıntı için ayrıca find(1) kılavuz sayfasına bakınız.


6
farklılıklar zaten belirtilmiş. eğer anlamadıysanız, cevaplar sizin için hiç fark etmeyebilir? STDOUT aynı - STDERR farklı (bu cevapla diğer hata mesajlarını alıyorsunuz) - $? farklı (başka bir hata oluşmadığında bu cevapla 0 "başarılı" dır - dev / null'a yönlendirilirken her zaman> 0 "başarılı değil") - belki birisinin "doğru" $ olması gerekir? bir senaryoda
Michael Brux

6
@Masi en belirgin kusur Jonathan'ın cevabı (grep -v) 'İzin reddedildi' içeren dosya adını hariç tutacak :)
Fruit

65
Başka bir arama kriteri eklemeniz gerekiyorsa, bununla birlikte yapılması gerektiğini buraya eklemenin uygun olduğunu düşünüyorum -o:find . ! -readable -prune -o -name '*.txt'
tempestadept

22
POSIX'in seçenek olarak findbulunmadığını unutmayın -readable; ne findBSD ve dolayısıyla Mac OS X için (diğer sistemlerden emin değilim). Yani, GNU findgarantinizin olduğu yerde , bu harika çalışıyor, ancak sistemin GNU'nun findyüklü olduğunu garanti edemezseniz, bunu nasıl uyarlayacağınız açık değildir . (Linux'ta iyi çalışır; başka bir yerde çalışabilir veya çalışmayabilir.)
Jonathan Leffler

6
find . ! -readable -prune -o -name '*.txt'4.2.2'yi kullanarak Ubuntu 14.04 üzerinde çalışmıyor gibi görünüyor. Görünüşe göre -name. Bazı garip nedenlerle başarım varfind . \( ! -readable -prune \) -o -name '*.txt' -print
con-f-use

110

Eğer aramayı "/" kökünden başlatmak istiyorsanız, büyük olasılıkla şöyle çıktılar göreceksiniz:

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

İzin yüzünden. Bunu çözmek için:

  1. Sudo komutunu kullanabilirsiniz:

    sudo find /. -name 'toBeSearched.file'

Süper kullanıcının şifresini sorar, şifreyi girdiğinizde gerçekten ne istediğinizi görürsünüz. Süper kullanıcı parolanız olmadığı anlamına gelen sudo komutunu kullanma izniniz yoksa, önce sistem yöneticisinden sizi sudoers dosyasına eklemesini isteyin.

  1. Standart Hata Çıktısını (Genellikle Görüntü / Ekran) 'dan bir dosyaya yönlendirebilir ve hata mesajlarını ekranda görmekten kaçınabilirsiniz! / dev / null özel bir dosyaya yönlendir:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. Standart Hata Çıkışını (Genel Olarak Ekran / Ekran) 'dan Standart çıkışa (Genel Olarak Ekran / Ekran) yönlendirebilir, ardından' İzin reddedildi 'çıkış hatlarını görmemek için -v "invert" parametresi ile grep komutlu boru kullanabilirsiniz. Kelime çiftleri:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'

7
@scottmrogowski, soruya cevap vermemesi dışında ... 1. sistem yöneticisinden sizi sudoers dosyasına eklemesini isteyin. 2.sudo find...
Stephen

1
tam olarak aradığım şey!
DankMasterDan

92

Kullanmak zorunda kaldım:

find / -name expect 2>/dev/null

ne bulmak istediğimin adını belirterek tüm hataları / dev / null'a yönlendirmesini söylerim

beklediğim bekle programının yeri olmayı bekliyorum.


3
@Masi, cevaptaki komut kullanılmıyor expect. Bunun yerine, expectbu komutun bulmaya çalışacağı dosyanın adıdır.
Dhruv Kapoor

2
Tek bir hata mesajı sınıfını yoksaymak için tüm stderr çıktılarını körü körüne yönlendirmek genellikle kötü bir fikirdir - süreçteki diğer tüm keyfi hataları kaybedersiniz.
Josip Rodin

59

Boru stderriçin /dev/nullkullanarak 2> / dev / null '

find . -name '...' 2>/dev/null


2
Mac OSX'te bile benim için iyi çalışıyor. Veya hattafind . -name '...' -print 2>/dev/null
shadowsheep

30

Ayrıca okunamayan dizinlere inmeyi önlemek için -permve -prunetahminlerini kullanabilirsiniz (ayrıca bkz. "İzin reddedildi" çıktı ifadelerini bulma programından nasıl kaldırabilirim? - Unix ve Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders

4
-perm -g+r,u+r,o+ryalnızca dosyanın güvenlik ilkelerinin rtümü için (okuma) iznine sahip olan ve geçerli kullanıcının bu dosyayı okuyabilip okuyamayacağı ile doğrudan bir ilişkisi olmayan dosyaları eşleştirir . Bu geçerli kullanıcının bu ikisi bayan dosyaları potansiyeline sahiptir edebilir okuyup bunu yapamazlar o dosyaları eşleşecek.
mklement0

Bence find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printiyi bir çözüm olurdu.
Mattia72

2
Mattia72 @: No, tamamen taklit temelde imkansız -readableolan -perm- önceki yorumu görmek ve bu örneği göz önünde bulundurun: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rbaskılar file, kendi kullanıcı biti ayarlandığında okumak için değil, o ilgilidir nobodykullanıcı değil, geçerli kullanıcı. Geçerli kullanıcı bu dosyayı okuyamaz; deneyin cat file. Ayrıca bakınız: bu cevabım .
mklement0

23

Standart hatayı yeniden yönlendir. Örneğin, bir unix makinesinde bash kullanıyorsanız, standart hatayı / dev / null dizinine şu şekilde yönlendirebilirsiniz:

find . 2>/dev/null >files_and_folders

20

Yukarıdaki yaklaşımlar Mac OS X için durumu ele almazken, Mac Os X -readableanahtarı desteklemediğinden , çıktınızdaki 'İzin reddedildi' hatalarından nasıl kaçınabilirsiniz. Bu birine yardımcı olabilir.

find / -type f -name "your_pattern" 2>/dev/null.

findÖrneğin, bir dizindeki belirli bir desenin dosya boyutunu bulmak için başka bir komut kullanıyorsanız , 2>/dev/nullaşağıda gösterildiği gibi çalışmaya devam eder.

find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$.

Bu, belirli bir desenin dosyalarının toplam boyutunu döndürür. Find 2>/dev/nullkomutunun sonundaki notu not edin .


OS X'e güzel ciltleme! Jonathan'ın cevabı kısmı açıklıyor 2>/dev/null. Lütfen kısmı açıklar mısınız -exec du -ch {} + 2>/dev/null | grep total$?
Léo Léopold Hertz 준영

1
@Masi Komut -exectarafından bulunan dosyalar veya dizinler üzerinde daha fazla işlem yapmak için seçenekli herhangi bir komutu kullanabilirsiniz find. du -ch file_patterneşleşen her dosyanın boyutunu hesaplar ve file_patternbu çıktı son satırı eşleşen tüm dosyaların genel toplamıdır file_pattern. İçin man sayfasına bakınız du. grep totalgenel toplamı (son satır olan) ayıklayan satırı filtreler.
Bunti

13

Bu hatalar standart hata çıkışına (fd 2) yazdırılır. Filtrelemek için tüm hataları / dev / null dizinine yönlendirmeniz yeterlidir:

find . 2>/dev/null > some_file

veya önce stderr ve stdout'a katılın ve sonra bu belirli hataları grep:

find . 2>&1 | grep -v 'Permission denied' > some_file

11

Basit cevap:

find . > files_and_folders 2>&-

2>&-tüm hata mesajlarının susturulması -için standart hata dosyası tanımlayıcısını ( 2) kapatır ( ) .

  • 1Herhangi bir ' Permission denied' hatası yazdırılırsa çıkış kodu yine de kalır

GNU için sağlam cevap find:

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

Fazladan seçenekler gönderir findo -prune(içine inen önlemek) ama yine de -printherhangi bir dizin ( (yok) ) her ikisine de sahip ve izinleri, ya da ( ) başka herhangi bir dosya.-typed\!-readable-executable-o-print

  • -readableve -executableseçenekler, POSIX standardının parçası olmayan GNU uzantılarıdır
  • Permission deniedAnormal / bozuk dosyalarda yine de ' ' dönebilir (örn., <V2.0.5 kullanan kapsayıcıya bağlı dosya sistemlerini etkileyen hata raporuna bakın lxcfs)

POSIX uyumlu find(GNU, OSX / BSD, vb.) İle çalışan sağlam yanıt

{ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1

Dizeyi içeren tüm satırları kaldırarak standart hata akışını iletmek için bir boru hattı kullanın .grep'Permission denied'

LC_ALL=Csetleri POSIX yerel bir kullanarak ortam değişkeni , 3>&2 2>&1 1>&3ve 3>&2 2>&1 yinelenen dosya tanımlayıcıları borusuna için standart hata akımı grepve [ $? = 1 ]kullanımları []tarafından döndürülen hata kodu ters çevirmek için grepözgün davranışı yaklaşmak için find.

  • Ayrıca 'Permission denied', çıktı yönlendirmesi nedeniyle oluşan hataları da filtreler (örneğin, files_and_foldersdosyanın kendisi yazılabilir değilse)

JordiFerran'ın cevap önerisi hakkında ne düşünüyorsunuz? - - Cevabını karşılaştırabilir misin?
Léo Léopold Hertz 준영

2
Bu yanıtın kabuk komut dosyası genel amaçlı değildir (yalnızca $ {m_find_name} ile eşleşen dizinleri listeler) ve soruyla ilgili olmayan birkaç seçenek içerir (nice, / home *, -maxdepth 5, -follow). Bu yanıt, genel amaçlı olarak kalırken 'okunabilir ancak yürütülebilir dizinleri filtreleme' konusunu daha açık bir şekilde ele almaktadır.
wjordan

1
@wjordan: Teşekkürler. Yorumlarımı kaldırdım, ancak bir nokta hala geçerli: -permtabanlı çözüm sunmaya değmez, çünkü alıntıdan daha temelde amaçlanandan farklı bir şey yapar : dosyanın sahibiyle ilgili tamamen dosya merkezli bir testtir ve grup, ikisi de komutu çağıran kullanıcı ile herhangi bir garantili ilişkisi yoktur (benim bu cevaba bakın . Gözden geçirilmiş GNU çözümünüz artık dosyalardan kaynaklanan izin reddedilen hataları yakalamıyor gibi görünüyor .
mklement0

Kullandığınız sözdizimini tanımıyorum (ne GNU ne de BSD olarak), ancak kendi kendine yeten bir örnekle benim açımı açıklayayım: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rbaskılar file, çünkü kullanıcı okuma biti ayarlanmış, ancak nobodykullanıcı ile ilgili , geçerli kullanıcı değil. Geçerli kullanıcı bu dosyayı okuyamaz; deneyin cat file.
mklement0

1
@ mklement0 tartışma için teşekkürler, başka bir testte açıkladığınız davranışı üretmeyi başardım (ilk seferinde neyi yanlış yaptığımı bilmiyorum), -permkullanıcının mevcut izinlerini belirlemek için işe yaramaz gibi görünüyor . Bu alternatifi bu yanıttan kaldırdı.
wjordan

4

Yalnızca izin reddedilen uyarılardan kaçınmak için bulmaya, okunamayan dosyaları aramadan budanarak yok saymayı söyleyin. Bulunuza bir ifade VEYA gibi bir ifade ekleyin.

find / \! -readable -prune -o -name '*.jbd' -ls

Bu çoğunlukla (okunamayan bir dosyayı eşleştirin ve listeden budanır ) VEYA ( * .jbd gibi bir adla eşleştirin ve [ls] ile görüntüleyin) der . (-VEYA kullanmadığınız sürece varsayılan olarak ifadelerin birlikte VE olduğunu unutmayın.) İkinci ifadede -ls'ye ihtiyacınız vardır, aksi takdirde bulmanız gereken her iki eşleşmeyi göstermek için varsayılan bir eylem ekleyebilir, bu da size tüm okunamayan dosyaları gösterecektir. .

Ancak sisteminizde gerçek dosyalar arıyorsanız, / dev'e bakmak için genellikle çok fazla dosya içeren bir neden yoktur, bu nedenle bu dizini hariç tutan bir ifade eklemeniz gerekir:

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

Yani (okunamayan dosyayı eşleştir ve listeden budama yap) VEYA (yol / dev ile eşleştir ve listeden budama yap) VEYA ( * .jbd gibi eşleme dosyası ve görüntüle) .


4

kullanım

sudo find / -name file.txt

Bu aptalca (aramayı yükselttiğiniz için) ve güvenli değil, ancak yazmak için çok daha kısa.


Burada tüm dosya sisteminde arama yaparsınız, yani bu "aramayı yükseltin". Neden güvenli değil diyorsun? Tüm dosya sistemini aradığı için mi?
Léo Léopold Hertz 준영

2
Çünkü sudo find komutunu temelde kötü bir fikir olan root izinleriyle çalıştırır. Ayrışma ve en az ayrıcalık ilkeleri ihlal edilmektedir.
sis

3
Buradaki "yükseklik", kök salma ayrıcalıklarına sahiptir sudo. Tüm sisteminizin, bir hata findveya kötü amaçlı bir sürümdeki bir hata veya beklenmedik bir şekilde bir şey yazan yanlış bir çağrıyla uğraşma riskiniz vardır; bu, normal ayrıcalıklarla çalıştırırsanız gerçekleşemez.
tripleee

2

Yukarıdaki cevapların hiçbiri benim için işe yaramadı. İnternette bulduğum her şey şuraya odaklanıyor: hataları gizle. Hiçbiri işlem dönüş kodunu / çıkış kodunu düzgün bir şekilde işlemez. Bazı dizinleri bulmak ve sonra içeriğini incelemek için bash komut dosyalarında command find komutunu kullanıyorum. Komut bulma başarısını çıkış kodunu kullanarak değerlendiriyorum: sıfır değeri çalışıyor, aksi takdirde başarısız oluyor.

Yukarıda Michael Brux tarafından verilen cevap bazen işe yarıyor. Ama başarısız olduğu bir senaryom var! Sorunu keşfettim ve kendim çözdüm. Ne zaman dosyaları budamak gerekir:

it is a directory AND has no read access AND/OR has no execute access

Burada önemli konuya bakın: VE / VEYA. Okuduğum iyi bir önerilen koşul dizisi:

-type d ! -readable ! -executable -prune

Bu her zaman işe yaramaz. Bu, bir eşleşme olduğunda erik tetiklendiğini gösterir:

it is directory AND no read access AND no execute access

Bu ifade dizisi, okuma erişimi verildiğinde ancak yürütme erişimi verilmediğinde başarısız olur.

Bazı testlerden sonra bunu fark ettim ve kabuk komut dosyası çözümümü şu şekilde değiştirdim:

nice find / home * / -maxdepth 5 -follow \
    \ (-type d -a ! \ (-readable -a -executable \) \) -prune \
    -o \
    \ (-type d -a-okunabilir -a - yürütülebilir -a-adı "$ {m_find_name}" \) -baskı

Buradaki anahtar, birleştirilmiş ifade için "doğru değil" ifadesini yerleştirmektir:

has read access AND has execute access

Aksi takdirde tam erişime sahip değildir, yani: budamak. Bu benim için daha önce önerilen çözümlerin başarısız olduğu bir senaryoda işe yaradığını kanıtladı.

Yorumlar bölümünde sorular için aşağıda teknik detayları sağlarım. Detaylar aşırı olursa özür dilerim.

  • Nice Neden nice komutunu kullanıyorsunuz? Burada bir fikrim var . Başlangıçta bir dosya sistemine bakarken işlem önceliğini azaltmanın iyi olacağını düşündüm. Betiğim birkaç dizinle sınırlı olduğundan bunun benim için bir anlamı olmadığını fark ettim. -Maksuppatı 3'e düşürdüm.
  • ¿Neden / home * / içinde arama yapmalı? Bu konu için geçerli değil. Tüm uygulamaları ayrıcalıklı olmayan kullanıcılarla (kök değil) derleyen kaynak kodu aracılığıyla elle yüklerim. "/ Home" içine kurulurlar. Birlikte yaşayan birden fazla ikili dosya ve sürümüm olabilir. Tüm dizinleri bulmam, master-slave tarzında incelemem ve yedeklemem gerekiyor. Birden fazla "/ home" (özel bir sunucu içinde çalışan birkaç disk) olabilir.
  • ¿Neden -follow kullanıyorsunuz? Kullanıcılar dizinlere sembolik bağlantılar oluşturabilir. Yararlılığı, bulunan mutlak yolların kaydını tutmam gerekiyor.

Cevabınız ve güzel gözlemleriniz için teşekkür ederiz! Cevabınızı daha iyi önizlemek için burada bir ödül açtım. Bence güzel bir bulgu okuma ve yürütme erişimini engellemiyor. - - Kullanmak neden açıklayabilir misiniz niceve find $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz 준영

2
Belirtildiği gibi kabuk komut dosyası genel amaçlı (sadece listeler dizinleri eşleştirme değil ${m_find_name}) ve sorumla ilgili olmayan çeşitli seçenekler içeriyor ( nice, /home*, -maxdepth 5, -follow). Genel amaçlı olarak kalırken 'okunabilir ancak yürütülebilir dizinleri filtrelememe' konusunu daha açık bir şekilde ele alan bir yanıt ekledim.
wjordan

2

Grep -v invert-match komutunu kullanabilirsiniz

-v, --invert-match        select non-matching lines

bunun gibi:

find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders

Sihir için olmalı


2

- = MacOS için = -

Takma ad kullanarak yeni bir komut oluşturun: ~ / .bash_profile satırını ekleyin:

alias search='find / -name $file 2>/dev/null'

ve yeni Terminal penceresinde şunu arayabilirsiniz:

$ file=<filename or mask>; search

Örneğin:

$ file = vb; arama


1

CSH veya TCSH kullanıyorsanız, işte bir çözüm:

( find . > files_and_folders ) >& /dev/null

Terminale çıkış yapmak istiyorsanız:

( find . > /dev/tty ) >& /dev/null

Ancak, "csh-whynot" SSS bölümünde açıklandığı gibi CSH kullanmamalısınız.


Tüm txt dosyalarını grep ve gizli dosyaları / dizini hariç tutmak, yazdırmak için "İzin reddedildi" iletisini atlamak istiyorum. Csh kabuğu kullanıyorum. Aşağıdaki komutları kullandım ve onlar bulmak çalışmıyor. -tip f -iname " .txt" -not -yolu '* / \. '| egrep -v "İzin reddedildi" bul. -tip f -iname " .txt" -not -yolu '* / \. '2> / dev / null Hata alınıyor. find: yollar ifadeden önce gelmelidir: 2 Kullanım: bul [-H] [-L] [-P] [-Olevel] [-D yardım | ağaç | arama | stat | oranları | opt | exec] [yol ...] [ifade]
yadav
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.