Bağımsız değişken listesi ls için çok uzun


48

ls *.txt | wc -lBirçok dosya içeren bir dizine çalışırken aşağıdaki hatayı alıyorum :

-bash: /bin/ls: Argument list too long

Bu "Bağımsız Değişken listesi" nin eşiği dağıtım veya bilgisayarın özelliklerine mi bağlı? Genellikle, bu kadar büyük bir sonucun sonucunu diğer bazı komutlara ( wc -lörneğin) aktarırdım , bu yüzden terminalin sınırlarıyla ilgilenmiyorum.


6
Bu, ayrıştırma lsçıktısını sayar , ki bu kötü bir fikirdir, bundan kaçının. Sayma için bkz. Dizindeki dosya sayısını saymanın en iyi yolu nedir? , zor bir geçici çözüm için neden döngünün "argüman çok uzun" hatası vermedi? .
Manatwork

@manatwork Evet, ben de bu soruları gördüm. Bir komuttan uzun bir çıktıyı daha genel bir şekilde kullanmak veya yönlendirmek için daha iyi bir yol merak ediyorum.

çoğu unix tabanlı sistemlerde sınır almak için getconf ARG_MAX yazılımını kullanabilirsiniz
Prasanth

Yanıtlar:


49

Kişisel hata mesajı argüman listesi çok uzun geliyor * ait ls *.txt.

Bu sınır, hem ikili programlar hem de Çekirdeğiniz için bir güvenliktir. Bu sayfada , onunla ilgili daha fazla bilgiyi ve nasıl kullanıldığını ve hesaplandığını göreceksiniz .

Boru boyutunda böyle bir sınır yoktur. Böylece sadece bu komutu verebilirsiniz:

find -type f -name '*.txt'  | wc -l

Not: Modern Linux'ta, dosya isimlerindeki garip karakterler (yeni satırlar gibi) lsya da gibi araçlarla kaçacak find, fakat yine de * ile gösterilecektir . Eski bir Unix kullanıyorsanız bu komuta ihtiyacınız olacak.

find -type f -name '*.txt' -exec echo \;  | wc -l

Not: Adında yeni satırlı bir dosyayı nasıl oluşturabileceğimi merak ediyordum. O kadar da zor değil, bir kere hileyi öğrendiğinde:

touch "hello
world"

1
İçinde yeni satır bulunan dosya isimleri varken çalışmalarında biraz değişiklik yaptım. -maxdepth 1Alt dizinlerdeki dosyaları saymayı düşünmüyorsanız, bir de eklemek isteyebilirsiniz .
Shawn J. Goff

İhtiyacın yok -exec echo \;.
Mikel

@ ShawnJ.Goff Test ettim. GNU bulunun şu anki sürümünde "yankı" gerekmez
Coren

@ Coren @Mikel - herkesin GNU'su yoktur find. findOS X ve üzerinde busybox tabanlı sistemler ve ben sayısı ile onun içinde bir satır, her şeyi arap saçına ile herhangi BSD tabanlı sistem yakalanan görünen dosya adını tahmin ediyorum.
Shawn J. Goff

Ha? wc -lnewlines sayıyor. Bu yüzden yeni hatlara sahip olmasını istiyoruz .
Mikel

11

Temel olarak Linux çekirdeğinin sürümüne bağlıdır.

Sisteminizin sınırını çalıştırarak görebilmeniz gerekir.

getconf ARG_MAX

Bu, size bir komut satırının kabuk tarafından genişletildikten sonra sahip olabileceği maksimum bayt sayısını gösterir.

Linux <2.6.23'te sınır genellikle 128 KB'dir.

Linux> = 2.6.25'te sınır ulimit -s, hangisi daha büyükse, 128 KB veya yığın boyutunuzun 1 / 4'ü (bkz ).

Tüm detaylar için execve (2) man sayfasına bakın.


Maalesef, boru hattı ls *.txtsorunu çözmeyecek, çünkü sınır kabukta değil işletim sisteminde.

Kabuk genişler *.txt, sonra aramaya çalışır.

exec("ls", "a.txt", "b.txt", ...)

ve *.txt128 KB sınırını aştığınız kadar eşleşen çok sayıda dosyanız var .

Gibi bir şey yapmak zorunda kalacaksın

find . -maxdepth 1 -name "*.txt" | wc -l

yerine.

(Ayrıca bkz. Shawn J. Goff'un yeni satırlar içeren dosya adları hakkındaki yorumları.)


Cevabını atamadığım için üzgünüm. Daha fazla üne ihtiyacım var. :(

Son satırda ne anlama geldiğini .ve ne -maxdepth 1anlama geldiğini açıklayabilir misiniz ? Teşekkürler! : D
Guilherme Salome

2
@ GuilhermeSalomé .geçerli dizin -maxdepth 1anlamına gelir, alt dizinlere bakmaz anlamına gelir. Bu aynı dosyaları eşleştirmek için tasarlanmıştır *.txt.
Mikel

9

Başka bir geçici çözüm:

ls | grep -c '\.txt$'

Olsa lsfazla çıktı üretir ls *.txtEğer geçen etmediklerinden, bu "çok uzun argüman" içine sorun çalışmaz üretir (veya üretmek için girişimlerde) herhangi argümanlar ls. Not grepBir dosya eşleştirme modeli yerine normal bir ifade alır.

Kullanmak isteyebilirsiniz:

ls -U | grep -c '\.txt$'

(sürümünüzü lsbu seçeneği desteklediğini varsayarsak ). Bu, lshem zamandan hem de bellekten tasarruf sağlayabilecek çıktısını sıralamamasını söyler - ve bu durumda sıra önemli değil, çünkü sadece dosyaları sayıyorsunuz. Çıktıyı sıralamak için harcanan kaynaklar genellikle önemli değildir, ancak bu durumda zaten çok fazla sayıda *.txtdosyanız olduğunu biliyoruz .

Tek bir dizinde çok fazla bulunmaması için dosyalarınızı yeniden düzenlemeyi düşünmelisiniz. Bu mümkün olabilir veya olmayabilir.


1

MAX_ARG_PAGES bir çekirdek parametresi gibi görünüyor. Kullanmak findve xargsbu sınırı ele almak için kullanılan tipik bir birleşimdir ancak bunun için çalışacağından emin değilim wc.

Çıktısını find . -name \*\.txtbir dosyaya aktarma ve bu dosyadaki satırları sayma bir geçici çözüm işlevi görmelidir.


lsÇıktısı olan her şeyi yapabilirsin, bunu çözmez. * .Txt jokerinin sınırı aşması halinde, lsherhangi bir çıktının başlatılması ve oluşturulmasından önce başarısız olur .
Manatwork

Doğru, cevabımı güncelledim.
Bram,

Daha iyi. Ancak bunun yerine geçmek için alt dizinleri tekrar tekrar taramaktan kaçınmayı lsbelirtmelisiniz -maxdepth 1.
Manatwork

Cevabını atamadığım için üzgünüm. Daha fazla üne ihtiyacım var. :(

0

Bu kirli olabilir ama ihtiyaçlarım için ve uzmanlığım dahilinde işe yarıyor. Çok hızlı performans gösterdiğini sanmıyorum ama günüme devam etmeme izin verdi.

ls | grep jpg | <something>

90.000 uzunluğunda bir jpg listesi alıyorum ve bir timelapse oluşturmak için avconv'a yönlendiriyordum.

Daha önce ls kullanıyordum * .jpg | avconv bu konuyu daha önce koştum.

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.