Neden * değil * ayrıştırma ls` (ve bunun yerine ne yapmalı)?


204

Kesin olarak "Ayrıştırma !" Diyerek bu bağlantıyı belirten cevapları sürekli görüyorum . Bu beni birkaç nedenden dolayı rahatsız ediyor:ls

  1. Görünüşe göre bu bağlantıdaki bilgiler küçük bir soru ile toptan olarak kabul edildi, ancak günlük okumada en azından birkaç hata bulabilirim.

  2. Aynı zamanda, bu bağlantıda belirtilen problemlerin bir çözüm bulma arzusu yaratmadığı anlaşılıyor.

İlk paragraftan itibaren:

... [ls]bir dosya listesi sorduğunuzda çok büyük bir sorun var: Unix, boşluk, yeni satırlar, virgüller, boru sembolleri ve kullanmaya çalıştığınız her şeyi içeren bir dosya adındaki hemen hemen her karaktere izin verir. NUL hariç sınırlayıcı. ... lsdosya adlarını yeni satırlarla ayırır. Adında yeni satırlı bir dosya olana kadar bu iyi. Ve bunun herhangi bir uygulamasını bilmediğim için, lsdosya isimlerini yeni satırlar yerine NUL karakterleriyle sonlandırabilmenizi sağlar, bu bize güvenli bir şekilde dosya isimlerinin bir listesini alamamıza neden olur ls.

Serseri, değil mi? Nasıl hiç bir yeni satır yeni satır içerebilir veriler için listelenen veri kümesi sonlandırıldı işleyebilir? Peki, bu web sitesindeki soruları cevaplayan insanlar günlük olarak böyle bir şey yapmadıysa, başımızın belada olduğunu düşünebilirim.

Gerçek şu ki, çoğu lsuygulama aslında çıktılarını ayrıştırmak için çok basit bir api sağlıyor ve bunu farkında bile olmadan hepimiz yapıyoruz. Bir dosya ismini sadece null ile sonlandırmakla kalmaz, bir null ile de başlatabilirsiniz ya da istediğiniz herhangi bir isteğe bağlı dizeyle başlatabilirsiniz. Dahası, bu keyfi dizeleri dosya türü başına atayabilirsiniz . Düşünün lütfen:

LS_COLORS='lc=\0:rc=:ec=\0\0\0:fi=:di=:' ls -l --color=always | cat -A
total 4$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 ^@^@^@^@dir^@^@^@/$
-rw-r--r-- 1 mikeserv mikeserv 4 Jul 10 02:18 ^@file1^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file2^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 02:27 ^@new$
line$
file^@^@^@$
^@

Bkz bu daha fazlası.

Şimdi bu makalenin bir sonraki kısmı beni gerçekten etkiliyor:

$ ls -l
total 8
-rw-r-----  1 lhunath  lhunath  19 Mar 27 10:47 a
-rw-r-----  1 lhunath  lhunath   0 Mar 27 10:47 a?newline
-rw-r-----  1 lhunath  lhunath   0 Mar 27 10:47 a space

Sorun şu ki ls, çıkarımdan ne siz, ne de bilgisayar, onun hangi kısımlarının bir dosya adı olduğunu söyleyemez. Her kelime mi? Hayır. Her satır mı? Hayır. Bu sorunun cevabından başka bir cevap yok: söyleyemezsin.

Ayrıca nasıl fark lsbazen dosya adı veri (bizim durumumuzda, artık geri garbles \nkelimeler arasında karakteri "a" ve "yeni satır" a içine ? Soru işareti ...

...

Geçerli dizindeki tüm dosyalar üzerinde sadece yineleme yapmak istiyorsanız, bir fordöngü ve bir küre kullanın:

for f in *; do
    [[ -e $f ]] || continue
    ...
done

Yazar, bu çağrılar dosya adlarını tahrifine zaman lskabuk globs içeren dosya adları listesini döndürür sonra ve bir dosya listesini almak için bir kabuk topak kullanılmasını önerir!

Aşağıdakileri göz önünde bulundur:

printf 'touch ./"%b"\n' "file\nname" "f i l e n a m e" |
    . /dev/stdin
ls -1q

f i l e n a m e  
file?name

IFS="
" ; printf "'%s'\n" $(ls -1q)

'f i l e n a m e'
'file
name'

POSIX tanımlar-1 ve -q lsböylece operandlar:

-q- Yazdırılamayan dosya adı karakterlerinin her bir örneğini ve <tab>s'nin soru işareti ( '?') karakteri olarak yazılmasını zorlayın . Çıktı bir terminal cihazında ise, uygulamalar bu seçeneği varsayılan olarak sağlayabilir.

-1- (Sayısal rakam bir.) Çıktıyı satır başına bir giriş olmaya zorlar.

Globbing kendi problemleri olmadan değildir - herhangi bir karakterle ?eşleşir, böylece bir listedeki çoklu eşleşme sonuçları aynı dosyayla birden çok kez eşleşir. Kolayca idare edilir.?

Bu şeyi nasıl yapılacağı da önemli değil - sonuçta yapılması gereken çok şey yok ve aşağıda gösteriliyor - Neden olmasın ilgimi çekti . Düşündüğüm kadarıyla, bu sorunun en iyi cevabı kabul edildi. Ben onlar insanlara ne anlatmaya daha sık odaklanmaya denemenizi öneririm olabilir ne üzerinde başka yapacak olamaz. En azından yanlış olduğunu kanıtlama ihtimalim çok daha az.

Ama neden denesin ki? Kuşkusuz, benim temel motivasyonum, başkalarının bana yapamayacağımı söylemeye devam etmesiydi. Ne lskadar aradığınızı bildiğiniz sürece , çıktının istediğiniz kadar düzenli ve tahmin edilebilir olduğunu çok iyi biliyorum. Yanlış bilgilendirme beni çoğu şeyden daha çok rahatsız ediyor.

Gerçek şu ki, hem Patrick'in hem de Wumpus Q'nun kayda değer istisnası dışında. Wumbley'nin cevapları (ikincisinin müthiş kulpuna rağmen) , buradaki cevaplardaki bilgilerin çoğunu çoğunlukla doğru buluyorum - bir kabuk küresi kullanımı daha basit. ve genel olarak mevcut dizini ararken, ayrıştırmaya göre daha etkilidir ls. Onlar benim konuda en azından yeterli bir sebep ya yukarıdaki makalede alıntı yanlış bilgilendirmeyi çoğaltım ne de kabul edilebilir gerekçe olan haklı, ancak değildir " ayrıştırmak asla ls. "

Lütfen Patrick'in cevaplarının tutarsız sonuçlarının çoğunlukla zsho zaman kullanmasının bir sonucu olduğunu unutmayın bash. zsh- varsayılan olarak - sözcük ayırma $(komutu yerine )taşınabilir bir şekilde sonuç vermiyor . Peki , dosyaların geri kalanının nereye gittiğini sorduğunda ? Bu sorunun cevabı kabuğun onları yedim. Bu yüzden taşınabilir kabuk kodunu SH_WORD_SPLITkullanırken zshve kullanırken değişkenleri ayarlamanız gerekir . Cevabında bunu not etmedeki başarısızlığını çok yanıltıcı olarak görüyorum.

Wumpus cevabı benim için hesaplamak değil - bir liste bağlamında ?karakter olan bir kabuk glob. Bunu nasıl söyleyeceğimi bilemiyorum.

Birden fazla sonuç elde etmek için, kürenin açgözlülüğünü sınırlamanız gerekir. Aşağıdakiler sadece korkunç dosya adlarının test temelini oluşturacak ve sizin için gösterecektir:

{ printf %b $(printf \\%04o `seq 0 127`) |
sed "/[^[-b]*/s///g
        s/\(.\)\(.\)/touch '?\v\2' '\1\t\2' '\1\n\2'\n/g" |
. /dev/stdin

echo '`ls` ?QUOTED `-m` COMMA,SEP'
ls -qm
echo ; echo 'NOW LITERAL - COMMA,SEP'
ls -m | cat
( set -- * ; printf "\nFILE COUNT: %s\n" $# )
}

ÇIKTI

`ls` ?QUOTED `-m` COMMA,SEP
??\, ??^, ??`, ??b, [?\, [?\, ]?^, ]?^, _?`, _?`, a?b, a?b

NOW LITERAL - COMMA,SEP
?
 \, ?
     ^, ?
         `, ?
             b, [       \, [
\, ]    ^, ]
^, _    `, _
`, a    b, a
b

FILE COUNT: 12

Şimdi olacak güvenli bir değil her karakter /slash, -dash, :colonardından bir kabuk glob içinde veya alfa-sayısal karakter sort -ubenzersiz sonuçlar için listeye. Bu güvenlidir, çünkü lsbizim için basılabilir olmayan karakterleri zaten güvenli bir şekilde uzaklaştırmıştır. İzlemek:

for f in $(
        ls -1q |
        sed 's|[^-:/[:alnum:]]|[!-\\:[:alnum:]]|g' |
        sort -u | {
                echo 'PRE-GLOB:' >&2
                tee /dev/fd/2
                printf '\nPOST-GLOB:\n' >&2
        }
) ; do
        printf "FILE #$((i=i+1)): '%s'\n" "$f"
done

ÇIKTI:

PRE-GLOB:
[!-\:[:alnum:]][!-\:[:alnum:]][!-\:[:alnum:]]
[!-\:[:alnum:]][!-\:[:alnum:]]b
a[!-\:[:alnum:]]b

POST-GLOB:
FILE #1: '?
           \'
FILE #2: '?
           ^'
FILE #3: '?
           `'
FILE #4: '[     \'
FILE #5: '[
\'
FILE #6: ']     ^'
FILE #7: ']
^'
FILE #8: '_     `'
FILE #9: '_
`'
FILE #10: '?
            b'
FILE #11: 'a    b'
FILE #12: 'a
b'

Aşağıda soruna tekrar yaklaşıyorum ancak farklı bir metodoloji kullanıyorum. Unutmayın - \0null dışında - /ASCII karakteri bir yol adında yasaklanan tek bayttır. Burada küreleri bir kenara koydum ve bunun yerine POSIX için belirtilen -dseçeneği lsve ayrıca belirtilen POSIX -exec $cmd {} +için yapıyı birleştirdim find. Çünkü findsadece hiç doğal olarak bir tane çıkarır /sırayla, kolayca aşağıdaki her giriş için tüm dentry bilgiler içeren bir özyinelemeli ve güvenilir sınırlandırılmış filelist tedarik etmektedir. Bunun gibi bir şeyle neler yapabileceğinizi hayal edin:

#v#note: to do this fully portably substitute an actual newline \#v#
#v#for 'n' for the first sed invocation#v#
cd ..
find ././ -exec ls -1ldin {} + |
sed -e '\| *\./\./|{s||\n.///|;i///' -e \} |
sed 'N;s|\(\n\)///|///\1|;$s|$|///|;P;D'

###OUTPUT

152398 drwxr-xr-x 1 1000 1000        72 Jun 24 14:49
.///testls///

152399 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
            \///

152402 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
            ^///

152405 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
        `///
...

ls -i çok yararlı olabilir - özellikle sonuç benzersizliği söz konusu olduğunda.

ls -1iq | 
sed '/ .*/s///;s/^/-inum /;$!s/$/ -o /' | 
tr -d '\n' | 
xargs find

Bunlar, düşünebildiğim en taşınabilir araç. GNU ile lsyapabilecekleriniz:

ls --quoting-style=WORD

Ve son olarak, burada inode sayılarına ihtiyaç duyduğumda oldukça sık kullandığım ayrıştırmals yöntemi daha basit :

ls -1iq | grep -o '^ *[0-9]*'

Bu sadece inode numaralarını döndürür - başka bir kullanışlı POSIX tarafından belirtilen seçenek.


12
@mikeserv Tamam yaptım. Shell Glob 2,48 kat daha hızlı. time bash -c 'for i in {1..1000}; do ls -R &>/dev/null; done'= 3.18s vs time bash -c 'for i in {1..1000}; do echo **/* >/dev/null; done'= 1.28s
Patrick

28
En son güncellemenizle ilgili olarak, lütfen kodunuzun çalıştığını belirlerken görsel çıktıya güvenmeyi bırakın. Çıktınızı gerçek bir programa aktarın ve programın dosya üzerinde bir işlem yapmasını sağlayın. Bu yüzden cevabımda kullanıyorum stat, çünkü her dosyanın varlığını kontrol ediyor. sedŞey ile altındaki bit işe yaramaz.
Patrick

57
Ciddi olamazsın. Sorunuzun açıkladığı tüm çemberlerin içinden atlamak ls, ilk etapta ayrıştırmamaktan daha kolay veya basit veya herhangi bir şekilde daha iyi olabilir ? Tarif ettiğiniz şey çok zor. Hepsini anlayabilmem için onu yapılandırmam gerekecek ve nispeten yetkin bir kullanıcıyım. Ortalama Joe'nuzun bunun gibi bir şeyle başa çıkmasını beklemeniz beklenemez.
terdon

46
Bir argüman seçmek için bir soru kullanmak için -1. lsÇıktının ayrıştırılmasının yanlış olmasının tüm nedenleri orijinal linkte (ve birçok başka yerde) iyi bir şekilde ele alınmıştır. OP bunu anlamak için yardım isterse bu soru uygun olurdu, ancak OP bunun yerine yanlış kullanımının uygun olduğunu kanıtlamaya çalışıyor.
R. ..

14
@mikeserv Sadece bu değil parsing ls is bad. Yapma for something in $(command)ve doğru sonuçlar elde etmek için kelime bölme güvenerek büyük çoğunluğu için kötü command'sbasit çıkışını bizde olmayan.
BroSlow

Yanıtlar:


184

Ben bu hiç de ikna değilim, ama Diyelim ki Tartışmanın iyiliği için varsayalım olabilir Eğer yeterince çaba sarf hazırsan, çıkışını ayrıştırmak lsbile "düşman" karşısında, güvenilir - Birisi kim yazdığınız kodu bilir ve bilerek kırmak için tasarlanmış dosya adlarını seçer.

Bunu yapabilseniz bile, kötü bir fikir olurdu .

Bourne kabuğu iyi bir dil değil. Aşırı taşınabilirlik diğer herhangi bir faktörden (örneğin autoconf) daha önemli olmadığı sürece, karmaşık bir şey için kullanılmamalıdır .

Çıktının ayrıştırılmasının lsbir kabuk betiği için en az dirençli yol gibi göründüğü bir sorunla karşılaşıyorsanız , bu, yaptığınız her şeyin kabuk için çok karmaşık olduğunu ve buradaki her şeyi yeniden yazmanız gerektiğini gösteren güçlü bir göstergedir . Perl veya Python. İşte Python'daki son programınız:

import os, sys
for subdir, dirs, files in os.walk("."):
    for f in dirs + files:
      ino = os.lstat(os.path.join(subdir, f)).st_ino
      sys.stdout.write("%d %s %s\n" % (ino, subdir, f))

Bunun dosya isimlerinde olağandışı karakterlerle herhangi bir sorunu yoktur - çıktı aynı şekilde lsbelirsizdir, ancak çıktı belirsizdir, ancak "gerçek" bir programda (bunun gibi bir demosunun aksine) önemi yoktur. os.path.join(subdir, f)doğrudan sonucunu kullanın.

Eşit derecede önemli ve yazdığınız şeyin tam aksine, altı ay sonra hala bir anlam ifade edecek ve biraz farklı bir şey yapması gerektiğinde değiştirmek çok kolay olacak. Örnekleme yoluyla, dotfiles ve editör yedeklemelerini hariç tutma ve her şeyi alfabetik sıraya göre bazename ile işleme koyma gereksinimi bulduğunuzu varsayalım:

import os, sys
filelist = []
for subdir, dirs, files in os.walk("."):
    for f in dirs + files:
        if f[0] == '.' or f[-1] == '~': continue
        lstat = os.lstat(os.path.join(subdir, f))
        filelist.append((f, subdir, lstat.st_ino))

filelist.sort(key = lambda x: x[0])
for f, subdir, ino in filelist: 
   sys.stdout.write("%d %s %s\n" % (ino, subdir, f))

5
Bu iyi. Bu for in | for inözyineleme söz konusu mu? Emin değilim. Olsa bile birden fazla olamaz, değil mi? Şu ana kadar bana mantıklı gelen tek cevap bu.
mikeserv

10
Özyineleme yok, sadece iç içe- fordöngüler. os.walksahnelerin ardında ciddi ağır kaldırma yapıyor, ancak bunun için endişelenmenize gerek yok lsya da findiçeride çalışmanız konusunda endişelenmenize gerek yok .
zwol

6
Teknik olarak, os.walkbir jeneratör nesnesini döndürür . Jeneratörler Python'un tembel listelerinin versiyonlarıdır. Dış for döngüsü her yinelendiğinde, jeneratör başlatılır ve başka bir alt dizinin içeriğini "verir". File::FindEğer yardımcı olursa, Perl'deki eşdeğer işlevselliktir .
zwol,

6
% 100 eleştirdiğiniz belgeyle ve Patrick ve Terdon'ın cevaplarıyla aynı fikirdeyim olduğunun farkında olmalısınız. Cevabım, çıktıların ayrıştırılmasını önlemek için ek ve bağımsız bir sebep sağlamaktı ls.
zwol

19
Bu çok yanıltıcıdır. Shell iyi bir programlama dili değil, sadece bir programlama dili olmadığı için. Bir betik dili. Ve bu iyi bir betik dilidir.
Miles Rout,

178

Bu bağlantı çok referanslanmıştır, çünkü bilgiler tamamen doğrudur ve çok uzun zamandır oradadır.


lsyazdırılamayan karakterleri glob karakterleriyle evet olarak değiştirir, ancak bu karakterler gerçek dosya adında değildir. Bu neden önemli? 2 neden:

  1. Bu dosya adını bir programa geçirirseniz, bu dosya adı aslında yoktur. Gerçek dosya adını almak için glob'u genişletmek zorunda kalacaktı.
  2. Glob dosyası birden fazla dosyayla eşleşebilir.

Örneğin:

$ touch a$'\t'b
$ touch a$'\n'b
$ ls -1
a?b
a?b

Nasıl aynı görünen 2 dosyamız olduğuna dikkat edin. İkisi de temsil edilirse, onları nasıl ayırt edeceksiniz a?b?


Yazar, ls kabuk küre içeren bir dosya adı listesi döndürdüğü zaman isimlendirici dosya isimlerini çağırır ve daha sonra bir dosya listesi almak için bir kabuk glob kullanılmasını önerir!

Burada bir fark var. Bir glob'ı geri aldığınızda, gösterildiği gibi, bu glob birden fazla dosyayla eşleşebilir. Bununla birlikte, bir glob ile eşleşen sonuçları tekrarladığınızda, bir glob değil, tam dosyayı geri alırsınız.

Örneğin:

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

Fark nasıl xxdçıktı gösterileri $fileçiğ karakterler içerdiği \tve \ndeğil, ?.

Kullanırsanız ls, bunun yerine şunu alırsınız:

for file in $(ls -1q); do printf '%s' "$file" | xxd; done
0000000: 613f 62                                  a?b
0000000: 613f 62                                  a?b

“Yine de yineleyeceğim, neden kullanmıyorsun ls?”

Verdiğin örnek aslında işe yaramadı. Çalışıyor gibi görünüyor, ama çalışmıyor.

Buna atıfta bulunuyorum:

 for f in $(ls -1q | tr " " "?") ; do [ -f "$f" ] && echo "./$f" ; done

Bir sürü dosya ismini içeren bir dizin hazırladım:

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6120 62                                  a b
0000000: 6120 2062                                a  b
0000000: 61e2 8082 62                             a...b
0000000: 61e2 8083 62                             a...b
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

Kodunu çalıştırdığımda şunu alıyorum:

$ for f in $(ls -1q | tr " " "?") ; do [ -f "$f" ] && echo "./$f" ; done
./ab
./ab

Diğer dosyalar nereye gitti?

Bunu deneyelim:

$ for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f"; done
stat: cannot stat ‘./a?b’: No such file or directory
stat: cannot stat ‘./a??b’: No such file or directory
./ab
./ab
stat: cannot stat ‘./a?b’: No such file or directory
stat: cannot stat ‘./a?b’: No such file or directory

Şimdi gerçek bir glob kullanalım:

$ for f in *; do stat --format='%n' "./$f"; done
./a b
./a  b
./ab
./ab
./a b
./a
b

Bash ile

Yukarıdaki örnek benim normal kabuğum oldu, zsh. Prosedürü bash ile tekrarladığımda, örneğinizle tamamen farklı bir sonuç seti daha alırım:

Aynı dosya kümesi:

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6120 62                                  a b
0000000: 6120 2062                                a  b
0000000: 61e2 8082 62                             a...b
0000000: 61e2 8083 62                             a...b
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

Kodunuzla radikal biçimde farklı sonuçlar:

for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f"; done
./a b
./ab
./ab
./a b
./a
b
./a  b
./ab
./ab
./a b
./ab
./ab
./a b
./a
b
./a b
./ab
./ab
./a b
./a
b

Bir kabuk glob ile mükemmel çalışıyor:

$ for f in *; do stat --format='%n' "./$f"; done
./a b
./a  b
./ab
./ab
./a b
./a
b

Bash'ın bu şekilde davranmasının nedeni, cevabın başında belirttiğim noktalardan birine geri dönüyor: "Dosya glob'u birden fazla dosyayla eşleşebilir".

lsa?bbirkaç dosya için aynı glob'u ( ) döndürüyor , bu yüzden bu glob'u her genişlettiğimizde, ona uyan her dosyayı elde ediyoruz.


Kullandığım dosyaların listesini nasıl yeniden oluşturabilirim:

touch 'a b' 'a  b' a$'\xe2\x80\x82'b a$'\xe2\x80\x83'b a$'\t'b a$'\n'b

Onaltılı kod olanları UTF-8 NBSP karakterleridir.


5
@mikeserv aslında çözümü bir küre döndürmez. Ben sadece bu noktayı netleştirmek için cevabımı güncelledi.
Patrick

18
"Gerisi değil"? Tutarsız davranış ve beklenmeyen sonuçlar, bu nasıl bir sebep değil?
Patrick

11
@mikeserv Sorunuz üzerine yorumumu görmediniz mi? Shell globbing, 2.5 kat daha hızlı ls. Ayrıca, kodunuzun çalışmadığı için test etmenizi istedim. Zsh'nin bunlarla ne ilgisi var?
Patrick

27
@mikeserv Hayır, hepsi hala bash için bile geçerlidir. Yine de söylediklerimi dinlemediğin için bu soruyu bitirdim.
Patrick

7
Ne düşünüyorum, biliyor ben olacağım bu cevabı upvote ve bunu söylediği her şeye katılıyorum madende netleştirmek. ;-)
zwol

54

Biraz deneyelim ve basitleştirelim:

$ touch a$'\n'b a$'\t'b 'a b'
$ ls
a b  a?b  a?b
$ IFS="
"
$ set -- $(ls -1q | uniq)
$ echo "Total files in shell array: $#"
Total files in shell array: 4

Görmek? Bu zaten orada yanlış. 3 dosya var ama bash 4 bildiriyor. Bunun sebebi, kendisine iletilmeden önce kabuk tarafından genişletilen setglobaların lsverilmesidir set. Bu yüzden aldın:

$ for x ; do
>     printf 'File #%d: %s\n' $((i=$i+1)) "$x"
> done
File #1: a b
File #2: a b
File #3: a    b
File #4: a
b

Veya eğer tercih ederseniz:

$ printf ./%s\\0 "$@" |
> od -A n -c -w1 |
> sed -n '/ \{1,3\}/s///;H
> /\\0/{g;s///;s/\n//gp;s/.*//;h}'
./a b
./a b
./a\tb
./a\nb

Yukarıdaki çalıştırıldı bash 4.2.45.


2
Bunu oyladım. Kendi kodunun seni ısırdığını görmek güzel. Ama yanlış anladığım için, doğru yapılamayacağı anlamına gelmez. Size bu sabah yapmanın çok basit bir yolunu gösterdim ls -1qRi | grep -o '^ *[0-9]*'- bu ayrıştırma lsçıktısı, dostum ve bu inode numaralarının bir listesini almak için bildiğim en hızlı ve en iyi yol.
mikeserv

38
@mikeserv: Zamanınız ve sabrınız varsa doğru yapılabilir . Ancak gerçek şu ki, doğası gereği hataya açık. Sen kendin yanlış yaptın. yararları hakkında tartışırken! Bu , onun için savaşan bir kişi bile doğru şekilde yapamazsa, ona karşı büyük bir grev. Ve ihtimaller, doğru yapmadan önce muhtemelen daha fazla zaman harcayacaksınız. Seni bilmiyorum ama çoğu insan, aynı kod satırına sahip asırlarca uğraşmaktan ziyade zamanlarıyla daha iyi yapıyor.
cHao

@Hao - Ben onun yararlarını iddia etmedim - Ben propagandasını protesto ettim.
mikeserv

16
@mikeserv: Buna karşı çıkan argümanlar sağlam ve haklı. Sen bile onlara gerçek olduğunu gösterdin.
cHao

1
@cHao - katılmıyorum. Bir mantra ve bilgelik arasında çok iyi bir çizgi yoktur.
mikeserv

50

Çıktısı ls -qhiç bir dünya değil. O kullanır ?"doğrudan görüntülenemiyor burada bir karakter var" demek. Globlar ?"Burada herhangi bir karaktere izin verilir" anlamına gelir.

Globların başka özel karakterleri var ( *ve []en azından ve []çiftin içinde daha fazlası var). Bunların hiçbiri tarafından kaçmaz ls -q.

$ touch x '[x]'
$ ls -1q
[x]
x

ls -1qÇıktıyı ele alırsanız bir dizi küre vardır ve onları genişletirseniz, yalnızca xiki kez elde edemezsiniz , [x]tamamen kaybedersiniz. Bir küre olarak, bir dize olarak kendi kendine uyuşmaz.

ls -q gözlerinizi ve / veya terminalinizi deli karakterlerden korumak, kabuğa geri besleyebileceğiniz bir şey üretmemek içindir.


42

Cevap basit: Özel davalarınız lsmümkün olan herhangi bir faydadan daha ağır basmalıdır. lsÇıktıyı ayrıştırmazsanız bu özel durumlar önlenebilir .

Buradaki mantra , kullanıcı dosya sistemine asla güvenmez ( asla kullanıcı girdisine güvenmeyene eşdeğerdir ). % 100 kesin, her zaman çalışır bir yöntemi yoksa, bu bile tercih yöntem olmalıdır lsaynısını yapar ama daha az kesin olarak. Terdon ve Patrick tarafından kapsamlı bir şekilde ele alındığı için teknik ayrıntılara girmeyeceğim . lsİş / prestijimin çizgideyken olduğu önemli (ve belki de pahalı) bir işlemde kullanmanın riskleri nedeniyle, önlenebilirse belirsizliği olmayan bir çözümü tercih edeceğimi biliyorum.

Bazı insanların kesinlik için risk almayı tercih ettiğini biliyorum , ancak bir hata raporu hazırladım .


33

İnsanların hiçbir zaman bir şey yapmamasını söylemesi gerekmiyor, çünkü kesinlikle olumlu olarak doğru bir şekilde yapılamıyor. Bunu yapabiliriz, ancak hem alan hem de zaman açısından daha az karmaşık, daha az verimli olabilir. Örneğin, "x86 montajında ​​asla büyük bir e-ticaret arka planı kurma" demek mükemmel olacaktır.

Şimdi elimizdeki konuya gelince: Gösterdiğiniz gibi, ls'yi ayrıştırıp doğru sonucu veren bir çözüm oluşturabilirsiniz - bu nedenle doğruluk bir sorun değildir.

Daha mı karmaşık? Evet, ancak bunu bir yardımcı fonksiyonun arkasına gizleyebiliriz.

Şimdi verimlilik için:

Alan verimliliği: Çözümünüz uniqkopyaları filtrelemeye dayanıyor , bu nedenle sonuçları tembel olarak oluşturamıyoruz. Yani ya O(1)karşı O(n)ya da her ikisi de var O(n).

Zaman verimliliği: En iyi durum uniqbu yüzden hala var bir HashMap yaklaşımını kullanır O(n)elemanlarının sayısında algoritmayı temin öyle muhtemelen olsa O(n log n).

Şimdi asıl sorun: sizin algoritması hala unsurları kullanmak için gerçekten dikkatli çok kötü bakmıyor iken tedarik ve n için elemanlar. Çünkü bu büyük bir fark yaratıyor. Diyelim ki \n\nbir kürek çekecek bir dosyanız olduğunu ??ve listedeki her 2 karakter dosyasını eşleştirin. Komik bir \n\rşekilde, sonuçta ortaya çıkacak ??ve aynı zamanda 2 karakter dosyasını de döndürecek başka bir dosyanız varsa .. bunun nereye gittiğini görüyor musunuz? Doğrusal davranış yerine üstel olan kesinlikle "daha kötü çalışma zamanı davranışı" olarak nitelendirilir. Bu, pratik bir algoritma ile teorik CS dergilerinde makale yazdığınızla arasındaki farktır.

Herkes doğru örnekleri sever mi? İşte başlıyoruz. "Test" adlı bir klasör oluşturun ve bu python betiğini, klasörün bulunduğu dizinde kullanın.

#!/usr/bin/env python3
import itertools
dir = "test/"
filename_length = 3
options = "\a\b\t\n\v\f\r"

for filename in itertools.product(options, repeat=filename_length):
        open(dir + ''.join(filename), "a").close()

Bunun yaptığı tek şey 7 karakter için 3 uzunluğundaki tüm ürünleri üretmek. Lise matematiği 343 dosya olması gerektiğini söylüyor. Peki bu baskı için gerçekten hızlı olmalı, o yüzden görelim:

time for f in *; do stat --format='%n' "./$f" >/dev/null; done
real    0m0.508s
user    0m0.051s
sys 0m0.480s

Şimdi ilk çözümünüzü deneyelim, çünkü bunu gerçekten alamıyorum.

eval set -- $(ls -1qrR ././ | tr ' ' '?' |
sed -e '\|^\(\.\{,1\}\)/\.\(/.*\):|{' -e \
        's//\1\2/;\|/$|!s|.*|&/|;h;s/.*//;b}' -e \
        '/..*/!d;G;s/\(.*\)\n\(.*\)/\2\1/' -e \
        "s/'/'\\\''/g;s/.*/'&'/;s/?/'[\"?\$IFS\"]'/g" |
uniq)

Linux nane 16 üzerinde çalışmak için burada bir şey (sanırım bu yöntemin kullanılabilirliği için hacimler konuşuyor).

Her neyse, yukarıdakiler hemen hemen yalnızca sonucu elde ettikten sonra filtrelendiği için, önceki çözüm en azından en kısa sürede hızlı olmalıdır (birinde inode numarası yoktur - ama bunlar güvenilmezdir, bu nedenle doğruluktan vazgeçersiniz).

Peki şimdi ne kadar sürüyor

time for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f" >/dev/null; done

almak? Gerçekten bilmiyorum, 343 ^ 343 dosya adını kontrol etmek biraz zaman alıyor - size evrenin sıcak ölümünden sonra söyleyeceğim.


6
Elbette, başka bir cevabın altındaki yorumlarda da belirtildiği gibi , “… ls'i ayrıştırıp doğru sonucu veren bir çözüm oluşturabileceğinizi gösterdiniz…” ifadesi aslında doğru değildir.
Joker

26

OP'nin Belirtilen Niyeti Ele Alındı

Önsöz ve orijinal cevabın gerekçesien son 2015-05-18 tarihinde güncellenmiştir.

: mikeserv (OP) onun sorusuna son güncellemesi belirtilen Ben do" ayıp bunu dikkate ben ilk olsa yanlış kaynağı işaret etmek bu soruyu sordum maalesef burada en upvoted cevap büyük ölçüde yanıltıcı ve. "

İyi tamam; Bunu ben bulmak için sadece benim anlamını açıklamak için nasıl anlamaya çalışırken çok zaman geçirdiği yerine bir utanç olduğunu hissetmek o ben soruyu tekrar okumak. Bu soru "yerine yanıtlardan daha [üreten] tartışmayı" sona erdi ve ağırlığında sona erdi metnin ~ 18K bile bir blog yazısı için uzun olacağını (açık konuşmak gerekirse, tek başına soru için).

Ancak StackExchange sizin sabun kutunuz değil ve blogunuz değil. Bununla birlikte, aslında, ikisini de en azından bit olarak kullandınız. İnsanlar, insanların gerçek sorularını yanıtlamak yerine "Noktadan Noktaya" yanıtınızı yanıtlamak için çok zaman harcadılar. Bu noktada, OP'nin, kesinlikle bir soru olmaya niyetli olmadığını açıkça belirttiğinden dolayı, formatımıza uygun olmayan bir soru olarak işaretleyeceğim.

Bu noktada cevabımın konuya gelip gelmediğinden emin değilim; Muhtemelen hayır, ama bazı sorularınıza yönlendirildi ve belki bir başkasına yararlı bir cevap olabilir; yeni başlayanlar gönlünü alıyor, bunlardan bazıları daha deneyimli olduktan sonra "bazen" dönüşmüyorlar. :)

Genel bir kural olarak...

lütfen kalan pürüzlü kenarları affedin; OP'ye doğrudan çok fazla zaman harcadım ... doğrudan OP'yi alıntılamak yerine (başlangıçta amaçlandığı gibi), özetlemeye ve parola vermeye çalışacağım.

[büyük ölçüde orjinal cevabımdan elden geçirilmiş]
dikkate alındığında, OP'nin cevapladığım sorulara verdiği vurguyu yanlış okuduğuma inanıyorum; Bununla birlikte, ele alınan noktalar gündeme getirildi ve cevapları o noktaya geldiğine ve diğer bağlamlarda ortaya çıktıklarını ve yeni başlayanlara tavsiyelerde bulunduğum gibi konulara değindiğimi düşündüğüm için cevapları büyük ölçüde bozulmadan bıraktım.

Orijinal yazı, çeşitli nedenlerden dolayı çeşitli makalelerin “ lsÇıktıyı ayrıştırma” ya da “ lsÇıktıyı asla ayrıştırmamalısınız” gibi tavsiyelerde bulunduğunu sordu .

Bu konuda benim önerdiğim çözüm, bu tür bir ifadenin örneklerinin, mutlak bir niceleyicinin bir zorunluluk [örneğin, "hiç [hiç] X" ile eşleştirildiği, biraz farklı şekillerde ifade edilen bir deyim örnekleri olduğu, «[Her zaman Y», «[hiç kimse] asla Z»] genel kurallar veya kurallar olarak kullanılması gereken ifadeler oluşturmak için, özellikle bir özneye yeni başlayanlara mutlak gerçekler olarak kullanılmak yerine verildiğinde, Bununla birlikte, bu ifadelerin belirgin şekli .

Yeni bir konu öğrenmeye başladığınızda ve neden başka bir şey yapmanız gerekebileceğini iyi anlayamıyorsanız, kabul görmüş genel kuralları istisnasız uygulamak, yalnızca daha deneyimli bir kişinin rehberliğinde olmazsa, iyi bir fikirdir. bu kendin. Artan beceri ve tecrübe ile, bir kuralın herhangi bir özel durumda ne zaman ve nasıl uygulanacağını belirleyebilirsin. Önemli bir tecrübe seviyesine ulaştığınızda, ilk etapta genel kuralın arkasındaki gerekçeyi anlayacaksınız ve bu noktada, kuralın arkasındaki nedenlerin hangi seviyede uygulanıp uygulanmayacağı konusunda kararınızı kullanmaya başlayabilirsiniz. Bu durum ve ayrıca belki de kaygı verici endişelerin olup olmadığına ilişkin olarak.

Ve o zaman belki bir uzman, "Kurallar" ı ihlal eden şeyler yapmayı seçebilir. Ama bu onları daha az "Kurallar" yapmazdı.

Ve, yani, eldeki konuya göre: Bence, bir uzman tam anlamıyla boğulmadan bu kuralı ihlal edebildiğinden, bir acemiye "bazen" den başladığını söylemeyi haklı çıkaracak bir yol görmüyorum Tamam lsçıktıyı ayrıştırmak için , çünkü: öyle değil . Ya da en azından kesinlikle yeni başlayanlar için doğru değil.

Piyonlarını her zaman merkeze koyarsın; açıklıkta tek parça, bir hareket; ilk fırsatta kale; piskoposlar öncesi şövalyeler; jant üzerinde bir şövalye korkunçtur; ve daima hesabınızı sonuna kadar gördüğünüzden emin olun! (Özür dilerim, üzgünüm, yorulmak, bu StackExchange satranç için.)

Kuralları, Kırılmaması mı?

Yeni başlayanlar için hedeflenen veya okunması muhtemel olan bir konuyla ilgili bir makale okurken sıklıkla şöyle şeyler görürsünüz:

  • " Hiç X yapmamalısın ."
  • "Asla Q yapmayın!"
  • "Z yapma!"
  • "Bir kişi hep Y yapmalı!"
  • "C, ne olursa olsun."

Bu ifadeler kesinlikle mutlak ve zamansız kuralları belirtse de, öyle değiller; bunun yerine, bu makaleleri okuyan yeni başlayanlar için en azından tartışmalı olarak uygun bir yol olan genel kuralları [aka "kurallar", "kurallara uygun kurallar", "temel bilgiler" vb.] belirtmenin bir yoludur. Bununla birlikte, sadece mutlak olarak belirtildiklerinden, kurallar kesinlikle profesyonelleri ve uzmanları [bu tür kuralları ilk önce özetleyenlerin, tekrarlayanlarla uğraşırken kazandıkları bilgileri kaydetmenin ve aktarmanın bir yolu olarak] bağlamaz. kendi zanaatlarındaki sorunlar.

Bu kurallar kesinlikle bir uzmanın karmaşık ya da farklı bir sorunla nasıl başa çıkacağını, bu kuralların birbiriyle çatışmayacağını; ya da ilk başta yönetime yönlendiren endişelerin basitçe geçerli olmadığı durumlar. Uzmanlar, korkmadılar (ya da korkmamalılar!) Sadece belli bir durumda bir anlam ifade etmediklerini bildikleri kuralları çiğniyorlar. Uzmanlar sürekli olarak mesleğindeki çeşitli riskleri ve kaygıları dengelemekle uğraşırlar ve bu tür kuralları çiğnemeyi, çeşitli faktörleri dengelemeyi ve takip etmek için sadece bir kurallar tablosuna güvenememeyi tercih etmek için yargılarını sık sık kullanmalıdırlar. Örnek Gotoolarak alın : Zararlı olup olmadıklarına dair uzun, tekrarlanan, tartışmalar oldu. (Evet, asla goto kullanmayın.; D)

Modal Bir Teklif

En azından İngilizcede tuhaf bir özellik ve genel kuralların bir çok başka dilinde hayal ettiklerini, modal bir teklifle aynı şekilde ifade edildiklerini, ancak bir alandaki uzmanların genel bir kural koymaya istekli oldukları yönünde durum, her zaman uygun olduklarında kuralı kıracaklarını bilerek. Açıkçası, bu nedenle, bu ifadelerin modal mantıktaki aynı ifadelere eşdeğer olması amaçlanmamıştır.

Bu yüzden sadece aptalca olmaları gerektiğini söylüyorum. Gerçekten "asla" veya "her zaman" bir durum olmaktan ziyade, bu kurallar genellikle çok çeşitli durumlarda uygun olma eğiliminde olan genel rehberlerin kodlanmasına hizmet eder ve yeni başlayanlar bunları kör bir şekilde takip ettiğinde, muhtemelen çok uzağa yol açabilir. iyi bir sebep olmadan onlara karşı çıkmayı seçen yeni başlayanlardan daha iyi sonuçlar. Bazen kurallara aykırı olduğunda yanlış seçimlere eşlik eden düpedüz hatalardan ziyade basitçe standartların altında sonuçlara yol açan kuralları kodlarlar.

Bu nedenle, genel kurallar yüzeyde göründüğü kesin modal önermeler değildir, bunun yerine kurala aşağıdaki gibi bir standart boyler plakasıyla verilen bir kısa yol vermenin yoludur:

bu kılavuzun belirli bir durumda yanlış olduğunu söyleme yeteneğiniz olmadığı ve kendinize haklı olduğunuzu kanıtlamadığınız sürece $ {RULE}

Elbette ls, $ {RULE} yerine "asla ayrıştırma çıktı" yı kullanabilirsiniz. :)

Ah evet! Ayrıştırma Çıktısı Hakkında Ne ls?

Öyleyse, tüm bunlara rağmen ... bu kuralın iyi bir kural olduğu açık. Her şeyden önce, gerçek kuralın yukarıda açıklandığı gibi, deyimsel olduğu anlaşılmalıdır ...

Ama ayrıca, sadece belirli bir durumda kırılıp kırılmayacağını bilmek için kabuk komut dosyası yazarken çok iyi olmak zorunda değilsiniz. Ayrıca, testte zorlamaya çalıştığınızda yanlış yaptığınızı söylemeniz de aynı derecede yetenek gerektiriyor ! Ve şunu söylüyorum, bu tür makalelerin muhtemel izleyicilerinin çok büyük bir çoğunluğunun (“çıktısını ayrıştırma ls!” Gibi tavsiyeler vererek ) bu şeyleri yapamayacağını ve bu tür becerilere sahip olanların muhtemelen bunu anlayacağına inanıyorum. kendi başlarına çözüyorlar ve yine de kuralı görmezden geliyorlar.

Ama ... sadece bu soruya bakın ve muhtemelen bu beceriye sahip insanların bile bunu yapmak için kötü bir çağrı olduğunu düşündü; ve sorunun yazarının şu anki en iyi örnek olan bir noktaya gelmek için harcadığı çaba! O kadar zor biri problem üzerinde size garanti, potansiyel ile yanlış ve orada alacağı dışarı insanların% 99 çok kötü sonuçlar! Karar verilen yöntem iyi bir sonuç olsa bile; o (ya da başka) lsayrıştırma fikri bir bütün olarak IT / geliştirici halk tarafından benimsenene kadar, çok sayıda teste (özellikle zamanın testine) dayanır ve son olarak 'ortak bir teknik' statüsüne geçmeyi başarır. birçok insan deneyebilir ve yanlış sonuçlara varabilir.

Yani, ben, o .... son bir kez yinelemek olacaktır özellikle bu durumda , yani neden " asla ayrıştırmak lsçıktı!" kesinlikle onu ifade etmek için doğru yoldur.

[GÜNCELLEME 2014-05-18: OP'nin yorumuna cevap vermek için cevabın gerekçesinin (yukarıda) açıklığa kavuşturulması; Aşağıdaki ek, OP’nin dünden bu soruya eklenmesine cevap olarak geliyor]

[GÜNCELLEME 2014-11-10: üstbilgi eklendi ve yeniden düzenlenmiş / yeniden düzenlenmiş içerik; ve ayrıca: yeniden biçimlendirmek, yeniden düzenlemek, açıklamak ve um ... "özlü ifadeler" ... bunun bir temizlik işi olmasına rağmen basitçe bir temizlik olmasını amaçlamıştım. bunu üzgün bir durumda bırakmıştım, bu yüzden çoğunlukla bazı siparişler vermeye çalıştım. ilk bölümü bozulmadan bırakmanın önemli olduğunu düşündüm; bu yüzden sadece iki küçük değişiklik var, gereksiz 'ama' kaldırıldı ve 'bu' üzerinde durdu.

† Başlangıçta bunu yalnızca aslımın bir açıklaması olarak düşündüm; ancak yansıma üzerine diğer ilaveler üzerinde karar

Posts Yazılara ilişkin talimatlar için https://unix.stackexchange.com/tour adresine bakın.


2
Asla aptalca değil. Bu hiçbir şeyin cevabı değil.
mikeserv

1
Hmm. Bu cevabın tatmin edici olup olmayacağını bilmiyordum ama kesinlikle tartışmalı olmasını beklemiyordum . Ve ben (demek istediğim) 'asla' kendi başına aptalca olmadığını iddia etmedim ; ama bu "Asla X yapmayın!" deyimsel bir kullanımdır . 'Asla ayrışma ls!' Diyebilen iki genel durum görüyorum . doğru tavsiyedir: 1. Çıktıyı çözümleyebilecek her kullanım durumunun, bir lsşekilde üstün, başka bir şekilde yapmadan, başka bir mevcut çözümü olduğunu (memnuniyetinize) gösterin . 2. Atıf vakalarında, ifadenin değişmez olduğunu gösterin.
shelleybutterfly

Sorunuza tekrar baktığımda, analizinize iyi gelen "asla ..." yerine "yapma ..." dan bahsettiğinizi görüyorum, bu yüzden de bu konuda netleşeceğim. Bu noktada, halihazırda memnuniyetinize gösterilmiş / açıklanmış olan ilk tipte bir çözüm var, bu yüzden oraya çok fazla girmeyeceğim. Fakat cevabımı biraz netleştirmeye çalışacağım: dediğim gibi, tartışmalı (veya çatışmalı) olmaya çalışmıyorum ama bu ifadelerin genel olarak nasıl amaçlandığını belirtmek istiyordum.
shelleybutterfly

1
O postayı temizlemeliyim. Yine de, hiçbir zaman bir değil ifade bunun doğru yol. İnsanların onlar başkalarına anlatmak için nitelikli düşünüyorum biraz saçma asla veya yok - sadece o iş ve neden sanmıyorum onlara, ancak çalışmak ve neden olacağını biliyorum. lsBir bilgisayar programıdır - Eğer ayrıştırmak bilgisayar çıktısı.
mikeserv

1
Olumsuz oyumu değiştirdim çünkü en azından işaretleme konusunda haklısın. Bu gece ya da yarın temizlemeye çalışacağım. Benim düşüncem, kod örneklerinin çoğunu sanırım bir cevaba taşıyacağım. Ancak yine de, endişelendiğim kadarıyla, belirtilen blog yazısı içindeki yanlışlıkları affedersiniz. Keşke insanlar bash el kitabını tamamen göstermeyi
bıraksalardı

16

lsBazı durumlarda çıktıların ayrıştırılması mümkün müdür ? Elbette. Bir dizinden bir inode numarası listesi çıkarma fikri iyi bir örnektir - uygulamanızın lsdesteklediğini biliyorsanız -qve bu nedenle her bir dosya tam olarak bir çıktı satırı üretecektir ve ihtiyacınız olan tek şey inode numaralarıdır ve bunları ayrıştırır. ls -Rai1qçıktı kesinlikle olası bir çözümdür. Elbette, yazar daha önce "ls'nin çıktısını asla ayrıştırma" gibi bir tavsiye görmemiş olsaydı, muhtemelen içinde yeni satır bulunan dosya adlarını düşünmezdi ve sonuç olarak 'q'yu bırakacaktı. Kod, bu durumda, gizlice bozulur - bu nedenle ayrıştırma lsçıktısının makul olduğu durumlarda bile , bu tavsiye hala faydalıdır.

Daha dar nokta komut dosyası kabuk için acemi (örneğin) ne dizindeki büyük dosya daha var, ya da ne bir dizin en son değiştirilen dosya daha var, onun ilk içgüdüsü ayrıştırmak için bir komut rakam dışarı çalıştığında, yani ls's Çıktı - anlaşılabilir çünkü lsbir aceminin öğrendiği ilk komutlardan biri.

Ne yazık ki, bu içgüdü yanlıştır ve bu yaklaşım bozulur. Maalesef, çok kırılgan bir şekilde kırıldı - çoğu zaman işe yarayacak, ancak kod konusunda bilgisi olan biri tarafından istismar edilebilecek ileri vakalarda başarısız oluyor.

Acemi ls -s | sort -n | tail -n 1 | awk '{print $2}', bir dizindeki en büyük dosyayı almanın bir yolu olarak düşünebilir . Ve adında boşluk olan bir dosya alana kadar çalışır.

Tamam, peki ya ls -s | sort -n | tail -n 1 | sed 's/[^ ]* *[0-9]* *//'? Adında yeni satır olan bir dosya olana kadar iyi çalışır.

Ekleyerek mu -qhiç lssavunmasından dosya adına bir satır varken yardımcı? Dosya adının aynı noktasında yazdırılamayan bir karakter içeren 2 farklı dosyaya sahip oluncaya kadar çıkmış gibi görünebilir ve daha sonra lsçıktısı hangisinin en büyük olduğunu ayırt etmenize izin vermez. Daha da kötüsü, "?" Yi genişletmek için, muhtemelen kabuğuna başvurur eval- bu, örneğin, bir dosyaya isabet ederse sorunlara yol açacaktır.

foo`/tmp/malicious_script`bar

Does --quoting-style=shell(eğer senin yardım lsbile destekler)? Hayır, hala görüntüleniyor mu? yazdırılamayan karakterler için, hangisinin en çok hangisinin en büyük olduğu belirsizdir. --quoting-style=literal? Hayır, aynı. --quoting-style=localeYa --quoting-style=cda en büyük dosyanın adını açıkça basmanız gerekiyorsa, ancak büyük olasılıkla dosyayla bir şey yapmanız gerekmiyorsa, muhtemelen alıntı yapmak ve gerçek dosya ismine geri dönmek bir demet kod olacaktır. Gzip diyelim ki, bunu söyleyebilirsiniz.

Ve tüm bu çalışmaların sonunda, sahip olduğu tüm muhtemel dosya isimleri için güvenli ve doğru olanı bile okunamaz ve sürdürülemez ve piton veya perl veya yakut içinde çok daha kolay, güvenli ve kolay bir şekilde yapılabilirdi.

Ya da diğer kabuk araçlarını kullanarak bile - kafamın üstünden, bunun hile yapması gerektiğini düşünüyorum:

find . -type f -printf "%s %f\0" | sort -nz | awk 'BEGIN{RS="\0"} END{sub(/[0-9]* /, "", $0); print}'

Ve en az olduğu gibi taşınabilir --quoting-styleolması gerekir.


Ah boyutu hakkında doğru - denedim eğer muhtemelen yapabilirim - yapmalıyım? Im tür yorgun ya bütün bunlar - Sen söyleme çünkü ben senin cevabını edemez veya yok veya hiç ama aslında belki örneklerini vermek neden ve karşılaştırılabilir başka nasıl teşekkür -.
mikeserv

Bence denersen, düşündüğünden çok daha zor olduğunu keşfedeceksin. Yani, evet, denemeyi tavsiye ederim. Onları düşünebildiğim sürece sizin için kıracak dosya isimleri vermeye devam etmekten mutlu olacağım. :)
godlygeek

Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
terdon

@mikeserv ve godlygeek, bu yorum dizisi taşımış sohbet etmek . Lütfen yorumlardaki böyle uzun tartışmalar yapmayın, sohbet bunun için var.
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.