Sembolleri yok sayarak bir dizinin içeriği


17

Ben sembolik bağlantıları göstermeden tüm içeriği (dosyalar ve alt dizinler) listelemek istiyorum bir dizin var. Linux'ta GNU yardımcı programları kullanıyorum. lsVersiyon 8.13.

Misal:

Tam dizin listesi:

~/test$ ls -Gg
total 12
drwxrwxr-x 2 4096 Jul  9 10:29 dir1
drwxrwxr-x 2 4096 Jul  9 10:29 dir2
drwxrwxr-x 2 4096 Jul  9 10:29 dir3
-rw-rw-r-- 1    0 Jul  9 10:29 file1
-rw-rw-r-- 1    0 Jul  9 10:29 file2
lrwxrwxrwx 1    5 Jul  9 10:29 link1 -> link1
lrwxrwxrwx 1    5 Jul  9 10:30 link2 -> link2

Ne almak istiyorum

~/test$ ls -somthing (or bash hack)
total 12
dir1 dir2 dir3 file1 file2

NOT: Ana motivasyonum, sembolik bağlantıları takip etmeden tekrarlayan bir grep (GNU grep 2.10) yapmaktır.

Yanıtlar:


28

Belirtilen soru için şunları kullanabilirsiniz find:

find . -mindepth 1 ! -type l

geçerli dizindeki veya sembolik olmayan alt dizinlerdeki tüm dosya ve dizinleri listeler.

mindepth 1sadece .geçerli dizin girişini atlamak içindir . Bunun eti, -type l"sembolik bir bağlantıdır" !anlamına gelen ve aşağıdaki testi reddetmek anlamına gelen kombinasyonudur . Kombinasyon halinde, sembolik olmayan her dosyayla eşleşirler. Bu, tüm dosyaları ve dizinleri özyinelemeli olarak listeler, ancak sembolik bağlantıları yoktur.

Sadece normal dosyaları (dizinleri değil) istiyorsanız:

find . -type f

Bu dizinin yalnızca doğrudan alt öğelerini dahil etmek ve diğerlerinin tümünü yinelemeli olarak dahil etmek için:

find . -mindepth 1 -maxdepth 1

İstediğiniz dosyaların listesini almak için bu (ve diğer) testleri bir araya getirebilirsiniz.

Kullandığınız greptestlerle eşleşen her dosyada belirli bir yürütme yapmak için şunu kullanın -exec:

find . -type f -exec grep -H 'some pattern' '{}' +

'{}'Dosyalarla değiştirilir. +Anlatmak için gerekli olan findkomut yapılır. Seçenek, -Hgrep'i tek bir eşleşen dosyayla çalıştırılsa bile bir dosya adı görüntülemeye zorlar.


Desenin bulunduğu cadıdaki dosyaları göstermez.
TheMeaningfulEngineer

Koştuğunuz şey budur grep(son paragrafa bakınız).
Michael Homer

Benim için çalışmıyorum. Sadece bulunan desenleri bulunduğu yerde bir dosya adı olmadan çıkarır.
TheMeaningfulEngineer

2
Kullan grep -H, eğer varsa (bkz.man grep ) veya başka bir şekilde grep 'pat' '{}' /dev/null ';'eğer yapmazsan birden fazla dosya vardır düşünerek içine kandırmak için.
Michael Homer

1
+sonunda yalnızca bir dosya veya bir dosya kaldığı dejenere durumda bu gereksinimi karşılayamaz.
Michael Homer

17

Veya daha basit:

ls -l | grep -v ^l

açıklama

ls -luzun biçimde listelemek anlamına gelir . Bunu yaptığınızda, ilk karakter dizesi her dosya hakkında bilgi verir. İlk karakter her dosyanın ne tür olduğunu belirtir. Eğer bir sembolik bağsa, lilk karakter a'dır .

grep -v ^l filtreleme anlamına gelir (-v ) ile başlayan satırları ( ^) an l.


Bu harika çalışıyor, ancak sadece klasör adlarını nasıl alabilirim? Bunu kullanmak istiyorumfor i in
Luka

Bu kodu açıklayabilir misiniz lütfen?
abg

Eğer ommit eğer bu çözüm çalışmadığını dikkat -liçinde ls. Yani bu beklendiği gibi çalışmaz:ls | grep -v ^l
stamster

@Luka Çıktısının üzerinden geçmiyorsunuzfind , bkz. Unix.stackexchange.com/questions/321697
Kusalananda

1
@abg - Bir açıklama ekledim. Umarım yardımcı olur.
Geoff

7

Sürüm 2.12'den itibaren, -r GNU grep seçeneği, elle belirtmediğiniz sürece sembolik bağlantıları kullanmaz:

-r, - yineleyici

Her dizinin altındaki tüm dosyaları, yalnızca komut satırındaysa, sembolik bağlantıları izleyerek, yinelemeli olarak okuyun. Bu, -d recurse seçeneğine eşdeğerdir.

-R, --Dereference-özyinelemeli

Her dizinin altındaki tüm dosyaları yinelemeli olarak okuyun. -R'den farklı olarak tüm sembolik bağlantıları takip edin.


Grep'in hangi versiyonu bu. Ben -R, -r, --recursive Read all files under each directory, recursively; this is equivalent to the -d recurse option.2.10 yılında
TheMeaningfulEngineer

grep (GNU grep) 2.14
tijagi

5

Zsh'de, glob elemeleri sayesinde bu kolay olurdu :

grep -- PATTERN **/*(.)

Kalıp **/, alt dizinleri özyinelemeli olarak hareket ettirir. Glob niteleyicisi. normal dosyalarla eşleştirmeyi kısıtlar.

Zsh olmadan kullanın find(bkz. Michael Horner'in cevabı ). Ve bu özel durumda, GNU grep istediğinizi yapabilir (tam olarak ne grep -ryapar) - ancak yalnızca 2.12 sürümünden beri, önceki sürümler sembolik bağlantıları izledi.


2

Bunu $LS_COLORSyapmak için kullanabilirsiniz . lsDestek sürümünüz bu değişkeni kullanarak renkleri belirtmeyi destekliyorsa, dosya türü başına çıktı tanımlayabilirsiniz. Yerleşik davranışı ve çok yapılandırılabilir. Bu yüzden bu gibi demo için bazı dosyalar oluşturdum:

for f in 9 8 7 6 5 4 3 2 1
    do touch "${f}file" && 
    ln -s ./"${f}file" ./"${f}filelink"
done

Şimdi yapacağım:

LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \
ls -1 --color=always | cat

###OUTPUT###
1file


HERE_THERE_BE_A_LINK>>1filelink@
2file


HERE_THERE_BE_A_LINK>>2filelink@
3file

...
HERE_THERE_BE_A_LINK>>8filelink@
9file
...

Ve sıfırlar da orada ...

LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \
ls -1 --color=always | sed -n l
1file$
$
$
\000HERE_THERE_BE_A_LINK>>\0001filelink@$
2file$
$
$
\000HERE_THERE_BE_A_LINK>>\0002filelink@$
3file$
...

Tüm dosya türlerini veya herhangi bir dosya türünü belirtebilirsiniz. Sadece tek bir dosya türü için bunu yapmak ls, terminal kaçışları için bazı varsayılan derleme değerlerini içerdiği için istediğinizi elde edemeyebilir . API'yi tek bir arayüz olarak ele almak için çok daha iyi bir şey yapardınız. Geçerli ortam dircolorsyapılandırılmış varsayılanları ayrıştırıp atamanın basit bir yolu :

LS_COLORS='rs=:no=//:lc=:rc=:ec=//:'$(
set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=/$fc//:"
done) ls -l --color=always | cat

Ana dizinimdeki çıktısı şöyle:

total 884
///-rw-r--r-- 1 mikeserv mikeserv    793 Jul  9 11:23 /fi//1/
//drwxr-xr-x 1 mikeserv mikeserv    574 Jun 24 16:50 /di//Desktop//
//-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 /fi//Terminology.log/
//-rw-r--r-- 1 mikeserv mikeserv      0 Jul  6 11:24 /fi//new
file/
//lrwxrwxrwx 1 mikeserv mikeserv     10 Jul 11 04:18 /ln//new
file
link/ -> /fi//./new
file/
//-rwxr-xr-x 1 mikeserv mikeserv    190 Jun 22 11:26 /ex//script.sh/*
//-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//shot-2014-06-22_17-10-16.jpg/
//-rw-r--r-- 1 mikeserv mikeserv     68 Jun 17 19:59 /fi//target.txt/

Bunu da ile çalıştırabilirsiniz cat -Ave karşılaşacağınız tek fark $, yeni satırlar için görmenizdir - tarafından basılamaz karakter yokturls --color=always bu yapılandırma ile - yalnızca burada gördüğünüz şeydir.

ls varsayılan terminal çıkışlarını şu şekilde ekler:

${lc}${type_code}${rc}FILENAME${lc}${rs}${rc}

... $lc (kodun solunda) , $rc (kodun sağında) ve $rs (sıfırla) için varsayılan değerler şunlardır:

 \033 - ESCAPE
 m - END ESCAPE
 0 - reset 

...sırasıyla. ${type_code}çeşitli fi (normal dosya - varsayılan ayar) , di (dizin) , ln (bağlantı) ve bildiğim diğer tüm dosya türleri için kullanılır. Ayrıca varsayılan olarak ayarlanmamış olan ve burada her satırın başında ile gösterilen $no (normal) vardır //. Basit küçük IFS=:bloğum, yapılandırılabilir her birinin adını kendi değeri olarak ekleyerek ve bir veya iki eğik çizgi ekleyerek çalışır - ancak \0NUL baytları da bunu yapar.

Varsayılan olarak ilk çıkışından hemen önce lsbir tane ekler - ancak bu burada doğru bir şekilde temsil edilmez. Bu durumda , her durumda geçerli olan (bitiş kodu) belirttim - belirtildiğinde, arasında başka bir şey elde edemezsiniz ve aksi halde - sadece bir dosya adının hemen ardından ve çıktı başında bir kez sunulur - birinci satırın başındaki ekstra eğik çizgide görebileceğiniz gibi.$rs$lc$ec $rs$rs$no${type_code}

İşte kendime ait bir pasaj $LS_COLORS

printf %s "$LS_COLORS"

rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:\
so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:\
or=40;31;01:su=37;41:sg=30;43:ca=30;41:\
tw=30;42:ow=34;42:st=37;44:ex=01;32:\
*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:...

Ve gerçekte, benim küçük kabuk hack'im muhtemelen aşırı derecede karmaşık - bu değerleri atamak için yaygın olarak mevcut bir arayüz var. dircolors -pKlibinde dene ve info dircolorsbu konuda daha fazla bilgi için.

Dosya adlarını rastgele dizelere sarabilirsiniz. İsterseniz bunları yorumlayabilirsiniz. Benzer davranışları yalnızca dosya uzantısına göre belirtebilirsiniz. Bu şekilde belirleyemeyeceğiniz çok fazla bir şey yok.

Şimdi sadece bunların hepsini uydurmuyorum - kazara kaynak kodunu tökezledikten sonra öğrendim .

Bu özel yapılandırma ile ls:

  1. $no - her kaydın başında kayıt başına bir kez

  2. ${type_code}- dosya türünün kısaltmasını içerecek şekilde her dosya adından hemen önce ve her zaman aynı satırda ve bir sembolik bağlantının hedefini belirten hemen sonra $no veya hemen ardından 7 boşlukla ayrılmış alanlar oluşur ->.

  3. $ec - ilk satırdan hemen önce ve sonra her dosya adını hemen takip eden bir kez.

  4. Diğer tüm değerler boş.

Takip eden şey boş değerlidir lsve bu sefer kullanacağım cat -A, onsuz son örnekle aynı görünecektir:

LS_COLORS='rs=:no=\0//:lc=:rc=:ec=\0//:'$(
set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=/$fc//\0:"
done) ls -l --color=always | cat -A

total 884$
^@//^@//-rw-r--r-- 1 mikeserv mikeserv    793 Jul  9 11:23 /fi//^@1^@//$
^@//drwxr-xr-x 1 mikeserv mikeserv    574 Jun 24 16:50 /di//^@Desktop^@///$
^@//-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 /fi//^@Terminology.log^@//$
^@//-rw-r--r-- 1 mikeserv mikeserv      0 Jul  6 11:24 /fi//^@new$
file^@//$
^@//lrwxrwxrwx 1 mikeserv mikeserv     10 Jul 11 04:18 /ln//^@new$
file$
link^@// -> /fi//^@./new$
file^@//$
^@//-rwxr-xr-x 1 mikeserv mikeserv    190 Jun 22 11:26 /ex//^@script.sh^@//*$
^@//-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//^@shot-2014-06-22_17-10-16.jpg^@//$
^@//-rw-r--r-- 1 mikeserv mikeserv     68 Jun 17 19:59 /fi//^@target.txt^@//$

Ve böylece, böyle bir ong listesindeki tüm sembolik bağlantıları güvenilir bir şekilde kaldırmak -liçin basit bir değişiklik yapabilirsiniz:

LS_COLORS='rs=:no=//:lc=:rc=:ec=/ :'$(
set -- di fi mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=$fc/:"
done)ln=///: ls -l --color=always | sed ':ln
\|///|{N;\|\n//|!bln};s|.*//||'

Çalıştırdıktan sonra sonuçlarım şöyle ...

total 884
-rw-r--r-- 1 mikeserv mikeserv    793 Jul  9 11:23 fi/1/ 
drwxr-xr-x 1 mikeserv mikeserv    574 Jun 24 16:50 di/Desktop/ /
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 fi/Terminology.log/ 
-rw-r--r-- 1 mikeserv mikeserv      0 Jul  6 11:24 fi/new
file/ 
-rwxr-xr-x 1 mikeserv mikeserv    190 Jun 22 11:26 ex/script.sh/ *
-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 fi/shot-2014-06-22_17-10-16.jpg/ 
-rw-r--r-- 1 mikeserv mikeserv     68 Jun 17 19:59 fi/target.txt/ 

Yukarıda yaptığım gibi bazı komutları kullanarak:

LSCOLORS=...$(...)fc1=///:fc2=///: ls ... | sed ...

... (burada fc1ve fc2sonra listelenen dosya türleri şunlardır set --alt kabukta) güvenilir Eğer tercih edebilir dosya türlerinden herhangi kombinasyonlarını kaldırmak için hizmet etmelidir lsdosya adları içerebilir herhangi karakterlerin bakılmaksızın çıktı.


Heh, güzel, özgünlük için +1. Ancak dizinleri boğmuş gibi görünüyor, bozuk bir ANSI renk kodu ile basılmışlar. Her neyse, bunun nasıl çalıştığına dair bir açıklama ekleyebilir misiniz? Belki ne olduğunu açıklamak lc, ncvb vardır?
terdon

@terdon - Onlar sadece ANSI ile basılmış konum zaten ortamında belirlenen ve ya bir varsayılan olarak derlenmiş kaçar lsbireyin di=değerinin. Bunu di=:ve diğerlerini geçersiz kılmak için var'a eklemeniz gerekir . Api ile kastettiğim bu - her dosya türüne hitap ediyorsunuz, ancak her durumda arayüze aynı şekilde hitap etmeniz gerekiyor. Bu nedenle, lntek bir yol ayarlamak ve divarsayılanları yoksaymak işe yaramaz. Derlenmiş birçok varsayılan var ... Hmm. Hakkında sorma lcve ncve malzeme geçerlidir - tamamen - Zaten o olsa geçen gün yaptı. Ben bağlayacağım, sanırım.
mikeserv

Ah, bu yüzden ya her zaman tüm olası dosya türlerini belirtmek ya da önceden neyin mevcut olduğunu kontrol etmek zorundayım? Tamam teşekkürler.
terdon

@terdon - düzenlememi şimdi gör - hepsini birkaç satır satırda yapar, her türü tür adına göre belirtir ve her dosya adını güvenilir bir şekilde sınırlar. Ayrıca, yazdırılamayan başka bir öğe de yoktur. Ve yine de bunun için bir API var - öyle dircolors. Bir yapılandırma dosyası okur ve bir kabuk evaldostu var değeri verir. Oldukça kolay - ama orada birkaç satır da var. Her neyse, kullanmak dircolorsistiyorsanız iki farklı dosyayı kaydedip bu şekilde çağırmanız yeterlidir. Ayrıca, geçen gün size \0her kaçış dizisinin bir parçası olarak NUL sınırlayıcılarıyla her ikisini birden nasıl yapacağınızı gösterdim .
mikeserv

@terdon - Derlenebilecek tüm değerleri ayarlamanın ne kadar kolay olduğunu açıklığa kavuşturmaya çalıştım - hepsini aldım, belki de çok fazla var ... LS_COLORS='rs=:no=\0//:lc=:rc=:ec=\0//:'$( set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex; for fc do printf %s "$fc=/$fc//\0:"; done) ls -l --color=always | cat -A
mikeserv

0

Yukarıdaki cevap aşağıdakilere yol açar:

 ls -1F | grep -i "/"

Garip bir şekilde ls komut 1 dışarı bırakarak hala bir liste verir.


1
Neden grep -i? Büyük /ya da küçük olabilir gibi değil . lsçıktı bir terminal olmadığında varsayılan olarak bir noe-sütun biçimidir (buradaki bir pipodur).
Kusalananda

-2

Bunu dene:

ls | grep -v " -> "

2
Bu çeşitli nedenlerle başarısız olur, örneğin adlı bir dosyada a -> b. Ayrıca, yeni satırları ve diğer tuhaflıkları olan dosya adlarında başarısız olur. Lütfen okuyun bu ls ayrıştırma kötü bir fikir niçin.
terdon

@terdon Bunun başarısız olmasının daha temel nedenleri var. Ya diğer adla lstakılır ls -lve bu, dosya adından önce sütunlar döndürür veya döndürmez ve bu sembolik bağlantılar hakkında özel bir şey yapmaz.
Gilles 'SO- kötü olmayı bırak

@terdon - lskendini ayrıştırır. lsbir terminale her baskı yaptığımızda hepimiz ayrışırız - bir API var . Burada böyle bir şey gösteren bir cevap gönderdim - ama çok daha fazlasını yapabilirsiniz. Size geçen gün gösterdim - kendiniz null olarak ayrılmış dosya adlarınız vardı.
mikeserv

@mikeserv biliyorum, biliyorum. Bununla birlikte, bunu nasıl güvenli bir şekilde yapacağınızı açıklamak, kendinizi gösterdiğiniz gibi birkaç yüz satır alır. Görüldüğü gibi, bu cevap l'leri ayrıştırmanın tüm tehlikelerinden muzdariptir ve OP açıkça bunların farkında değildir.
terdon

@terdon - lsçocuklarınızı ya da başka bir şeyi yemez - bu sadece bir programdır. Sonra anlatmaya yoksa o olacak anlatmaya birkaç yüz almak ve sadece bağlantılı birkaç yüz hatları yanlış neden daha birkaç yüz açıklamak. Ve ayrıca - bu sadece iki satır:LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \ ls -1 --color=always | cat
mikeserv

-3

Bu komutu deneyin: ls -p | grep -v @


Hayır, bağlantıları listeler.
TheMeaningfulEngineer

@Alan: k denemek bufind -type f
Thushi

1
-1 çünkü: i) -pSadece dizinlere bir eğik çizgi ekler, -Fii) findalternatifiniz dizinleri listelemeyecektir ve iii) Lütfen göndermeden önce cevaplarınızı test edin.
terdon
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.