Herhangi biri ls, dizin adları listesi için bir şey yapmak ve her birini döngüden geçirmek ve bir şeyler yapmak için bir şablon kabuk betiğine sahip mi?
ls -1d */Dizin adlarının listesini almak için yapmayı planlıyorum .
Herhangi biri ls, dizin adları listesi için bir şey yapmak ve her birini döngüden geçirmek ve bir şeyler yapmak için bir şablon kabuk betiğine sahip mi?
ls -1d */Dizin adlarının listesini almak için yapmayı planlıyorum .
Yanıtlar:
@ Shawn-j-goff ve diğerlerinin önerdiği gibi, bir kürenin yapacağı yerde kullanılamaz.
Sadece bir for..do..donedöngü kullanın :
for f in *; do
echo "File -> $f"
done
Sen değiştirebilirsiniz *ile *.txtya da (bu konuda dosya, dizin, ya da bir şey) bir listesini döndürür başka bir topak, bir liste üreten bir komut, örneğin $(cat filelist.txt), ya da aslında bir liste ile değiştirin.
doDöngü içinde sadece dolar işareti önekine sahip döngü değişkenine bakın ( $fyukarıdaki örnekte olduğu gibi). Yapabilirsin echoya da istediğin başka bir şey yapabilirsin.
Örneğin .xml, geçerli dizindeki tüm dosyaları yeniden adlandırmak için .txt:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
Ya da daha iyisi, eğer Bash kullanıyorsanız, alt kabuk oluşturmak yerine Bash parametre genişletmelerini kullanabilirsiniz:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
forDöngülerin çok suiistimal edildiğini ve çıktısını ayrıştırmaya çalışan tipik bir tuzak olduğunu gösterir ls. @ DanielA.White, sen belki o yardımcı olmadı (veya potansiyel yanıltıcı) eğer gibi söylediğinden beri, dizinler göre hareket ediyoruz, bu cevabı unaccepting düşünün. Shawn J. Goff'un cevabı, sorununuza daha sağlam ve çalışan bir çözüm sağlamalıdır.
ls , çıktıyı bir fordöngüde okumamalısınız , $()`` yerine kullanmalı ve More Quotes ™ kullanmalısınız . @CoverosGene'in iyi niyetli olduğundan eminim, ama bu çok korkunç.
lsolduğunu ls -1 | while read line; do stuff; done. En azından bu bir boşluk için kırılmayacak.
mv -vİhtiyacınız olmayanecho "moved $x -> $t"
lsDosya adlarını almak için çıktısını kullanmak kötü bir fikirdir . Arıza ve hatta tehlikeli senaryolara yol açabilir. Bunun nedeni, bir dosya adının karakter /ve karakter dışında herhangi bir karakter içermesi ve bu nullkarakterlerden herhangi lsbirini sınırlayıcı olarak kullanmamasıdır, bu nedenle bir dosya adında boşluk veya yeni satır varsa , beklenmeyen sonuçlar elde edersiniz.
Dosyalar üzerinde yineleme yapmanın çok iyi iki yolu vardır. Burada basitçe echodosya adıyla bir şeyler yaptığımı göstermek için kullandım ; Yine de her şeyi kullanabilirsiniz.
İlki, kabuğun doğal globbing özelliklerini kullanmaktır.
for dir in */; do
echo "$dir"
done
Kabuk */, fordöngünün okuduğu ayrı argümanlara genişler ; dosya foradında boşluk, satırsonu veya başka herhangi bir garip karakter olsa bile, her bir tam adı bir atom birimi olarak görecek; Listeyi hiçbir şekilde ayrıştırmıyor.
Eğer alt dizinleri içine yinelemeli gitmek istiyorsanız sizin kabuk gibi bazı genişletilmiş globbing özelliklere (olmadıkça, o zaman bu yapmayacağım bashs' globstarKabuk bu özelliklere sahip değilse. Veya sağlamak istiyorsanız sizin komut çalışacağını çeşitli sistemlerde, bir sonraki seçenek kullanmaktır find.
find . -type d -exec echo '{}' \;
Burada, findkomut arayacak echove dosya isminin bir argümanını iletecektir. Bu bulduğu her dosya için bir kez yapar. Önceki örnekte olduğu gibi, dosya listesinin ayrıştırılması yoktur; bunun yerine, bir dosya tamamen bağımsız değişken olarak gönderilir.
-execArgümanın sözdizimi biraz komik görünüyor. findilk argümanı sonra alır ve -execçalışacak program olarak ve sonraki her argümanda, o programa geçmek için argüman olarak kabul eder. Görmesi -execgereken iki özel argüman var . İlki {}; bu argüman, önceki bölümlerin findoluşturduğu bir dosya adı ile değiştirilir . İkincisi ;, bunun findprograma iletilecek olan argümanlar listesinin sonu olduğunu bilmesini sağlayan ; findBuna ihtiyacı var çünkü findexec'd programı için amaçlanan ve amaçlanmayan daha fazla argümanla devam edebilirsiniz . Bunun nedeni \, kabuğun da davranmasıdır.;özel olarak - bir komutun sonunu temsil eder, bu yüzden ondan kaçmamız gerekir, böylece kabuk findonu kendisi için tüketmekten ziyade bir argüman olarak verir ; özel olarak işlem görmemesi için kabuğun elde edilmesinin bir başka yolu tırnak içine almaktır: bu amaçla ';'olduğu gibi çalışır \;.
find. Yapılabilecek büyü var ve hatta algılanan sınırlamaları bile -execçözülebiliyor. -print0Seçeneği de kullanılmak için değerlidir xargs.
İçinde boşluk olan dosyalar için aşağıdaki gibi bir değişkeni alıntıladığınızdan emin olmalısınız:
for i in $(ls); do echo "$i"; done;
veya giriş alanı ayırıcı (IFS) ortam değişkenini değiştirebilirsiniz:
IFS=$'\n';for file in $(ls); do echo $i; done
Son olarak, ne yaptığınıza bağlı olarak, ls'ye ihtiyacınız olmayabilir:
for i in *; do echo "$i"; done;
\nyetersiz. Çıktısını ayrıştırmayı önermek hiçbir zaman iyi bir fikir değildir ls.
Eğer GNU Parallel http://www.gnu.org/software/parallel/ kurulu ise bunu yapabilirsiniz:
ls | parallel echo {} is in this dir
.Txt dosyasının tümünü .xml olarak yeniden adlandırmak için:
ls *.txt | parallel mv {} {.}.xml
Daha fazla bilgi için GNU Parallel için tanıtım videosunu izleyin: http://www.youtube.com/watch?v=OpaiGYxkSuQ
Neden IFS'yi yeni bir satıra ayarlamıyor, sonra lsbir dizideki çıktısını alıyorsunuz? IFS'yi yeni satıra ayarlamak, komik karakterlerle ilgili sorunları dosya adlarında çözmelidir; lsBir sıralama düzeni tesisi olduğundan, kullanmak güzel olabilir.
(Testte, IFS'yi ayarlamakta zorluk çekiyordum \nancak burada başka bir yerde önerildiği gibi newline backspace çalışmalarına ayarlamakta zorlandım ):
Örneğin (istenilen lsarama kalıbının geçtiğini varsayarsak $1):
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
FILES=($(/bin/ls "$1"))
for AFILE in ${FILES[@]}
do
... do something with a file ...
done
IFS=$SAVEIFS
Bu özellikle OS X'te kullanışlıdır, örneğin, oluşturma tarihine göre (en eskiden en yeniye) sıralanan dosyaların listesini yakalamak için lskomuttur ls -t -U -r.
\nyetersiz. Yalnızca geçerli çözümler, yol adı genişletmeli bir for döngüsü kullanır veya find.
Bunu böyle yapıyorum, ancak muhtemelen daha etkili yollar var.
ls > filelist.txt
while read filename; do echo filename: "$filename"; done < filelist.txt
ls | while read i; do echo filename: $i; done