Özel sınırlayıcı ile birden çok dosya adı satırını birleştirmek nasıl?


441

Sonucunu ls -1tek bir satıra birleştirmek ve istediğim şeyle sınırlandırmak istiyorum.

Bunu başarmak için kullanabileceğim standart Linux komutları var mı?

Yanıtlar:


689

İlk seçeneğe benzer, ancak sondaki sınırlayıcıyı atlar

ls -1 | paste -sd "," -

29
Bir not olarak, denediğim macun sürümü sonunda STDIN'den okumasını söylemek için bir "-" argümanı gerektirir. Örneğin ls -1 | paste -s -d ":" - , tüm macun sürümleriyle evrensel olup olmadığından emin değilim
Andy White

4
Bu daha iyidir çünkü boş sınırlayıcıya izin verir :)
Yura Purbeev

2
Not varsayılan olarak pastealır -(standart girdi), en azından benim paste (GNU coreutils) 8.22.
fedorqui 'SO zarar vermeyi durdur'

1
Ben sadece oyladı, bu ve şimdi seçilen cevapla aynı oylara sahip. CEVAP BU. izleyen
sınırlayıcı

1
Boş sınırlayıcı kullanılarak belirtilebilir "\0", bu yüzden paste -sd "\0" -benim için çalıştı!
Brad Parks

379

EDIT : Basitçe " ls -m " Eğer sınırlayıcı virgül olmasını istiyorsanız

Ah, güç ve basitlik!

ls -1 | tr '\n' ','

" , " Virgülünü istediğiniz gibi değiştirin. Bunun bir "sondaki virgül" içerdiğini unutmayın


46
+1, ancak daha ayrıntılı bir sürüm son \ n farklı şekilde
işlemelidir

5
Dosya adı içinde bir \nvarsa, bu da onun yerini alacaktır.
codaddict

3
@ShreevatsaR: "sonuna" son vermemek anlamına geliyor. " böylels -1 | tr "\\n" "," | sed 's/\(.*\),/\1/'
Chris

7
@Chris: sedson işaret karakteri ile biraz daha verimli olabilirsiniz:ls -1 | tr "\\n" "," | sed 's/,$//'; echo ''
pieman72

2
Kullanılması sedsonra trsadece son sembolü kaldırmak gibi görünüyor mantıksız görünüyor. ls -1 | tr '\n' ',' | head -c -1
İle

29

Bu, son virgülün yerine yeni bir satır gelir:

ls -1 | tr '\n' ',' | sed 's/,$/\n/'

ls -m ekran genişliği karakterine yeni satırlar ekler (örneğin, 80. karakter).

Çoğunlukla Bash (sadece lsharici):

saveIFS=$IFS; IFS=$'\n'
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS

Bash 4'te readarray(aka mapfile) kullanma :

readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS

Öneriler için gniourf_gniourf'a teşekkürler.


Bu, adında beyaz boşluk bulunan dosyalarla ilgilenmez. Bunu deneyin: dir = / tmp / testdir; rm -rf $ dir && mkdir $ dir && cd / $ dir && touch "bu bir dosyadır" this_is_another_file && ls -1 && files = ($ (ls -1)) && list = $ {dosya [@] /% / ,} && list = $ {list% *,} && echo $ list
dimir

1
@dimir: Bu sorunun cevaplarının çoğu bu sorundan muzdarip. Cevabımı, sekmeli veya boşluklu dosya adlarına izin vermek için düzenledim, ancak yeni satırlar düzenlemedim.
sonraki duyuruya kadar duraklatıldı.

Bash sürümünüzde de yol adı genişletmeleri var. Hatlarından bir dizi oluşturmak için kullanmayı düşünün lütfen mapfileolarak (Bash ≥4): mapfile -t files < <(ls -1). Keman yapmaya gerek yok IFS. Ve bu da daha kısa.
gniourf_gniourf

Eğer dizinizi sahip olunca kullanabileceğiniz IFSalanları katılmak için: saveIFS=$IFS; IFS=,; list=${files[*]}; IFS=$saveIFS. Ya da birden fazla karaktere sahip bir ayırıcı istiyorsanız başka bir yöntem kullanın.
gniourf_gniourf

1
@gniourf_gniourf: Önerilerinizi cevabıma ekledim. Teşekkürler.
sonraki duyuruya kadar duraklatıldı.

24

Bence bu harika

ls -1 | awk 'ORS=","'

ORS "çıktı kayıt ayırıcısı" olduğundan, şimdi satırlarınız virgülle birleştirilecektir.


6
Bu, sondaki sınırlayıcıyı hariç tutmaz.
Derek Mahar

6
Bu, özellikle çok karakterli kayıt ayırıcılarının (ör. " OR ") Kullanılması nedeniyle harika
Mat Schaffer

15

Ayar IFSve kullanım kombinasyonu "$*"istediğinizi yapabilir. Subshell kullanıyorum, bu yüzden bu kabuğun $ IFS'ine müdahale etmiyorum

(set -- *; IFS=,; echo "$*")

Çıktıyı yakalamak için,

output=$(set -- *; IFS=,; echo "$*")

2
Nasıl setçalıştığı hakkında daha fazla bilginiz var mı? Bana biraz vudu gibi gözüküyor. sığ bakmak da man setbana çok fazla bilgi net değildi.
Ehtesh Choudhury

3
setBir grup argüman verirseniz , ancak seçenek yoksa, konum parametrelerini ayarlar ($ 1, $ 2, ...). ilk argümanın (veya bu durumda dosya adının) kısa çizgi ile başlaması durumunda --korumak için oradadır set. İçindeki --seçeneğin açıklamasına bakın help set. Konum parametrelerini bir şeylerin listesini işlemek için uygun bir yol olarak görüyorum. Ben de bir dizi ile bu uygulanmış olabilir:output=$( files=(*); IFS=,; echo "${files[*]}" )
glenn jackman

Bu, herhangi bir ek programın yürütülmesini gerektirmediği ve boşluk veya hatta satırsonu içeren dosya adlarıyla çalıştığı için harikadır.
Eric

1
Sana type setsöyleyeceğim gibi set is a shell builtin,. Yani, man setyardımcı help setolmayacak , ama yapacak. Cevap: "- Konum parametrelerine kalan bağımsız değişkenleri atayın."
Stéphane Gourichon

Sonra set -- *. Genişlemesini geciktirme *bir düzey Bir alt kabuk gerek kalmadan doğru çıktı alabilirsiniz: IFS=',' eval echo '"$*"'. Tabii ki bu pozisyon parametrelerini değiştirecek.
Isaac


9

Tekerleği yeniden icat etme.

ls -m

Tam olarak bunu yapıyor.


OP virgül dönüştürmek için hala bir tr gerekir böylece herhangi bir sınırlayıcı istedi. Ayrıca virgüllerden sonra bir boşluk ekler; yani dosya1, dosya2, dosya3
rob

böylece virgül sonra boşluk kaldırmak için ls -mve kullanaraktrls -m | tr -d ' '
Andy

2
tr kullanımı dosya adları içindeki boşlukları siler. kullanımı daha iyised 's/, /,/g
glenn jackman

7

sadece bash

mystring=$(printf "%s|" *)
echo ${mystring%|}

5
Biraz daha verimli kullanmak için "printf -v mystring"% s | "*" - $ ()
camh

Ama özellikle izini |boğmaz, @camh.
Christopher

1
Eh, sadece bashve gnu coreutilsprintf
ThorSummoner

@camh Ancak printf -vverilen cevap birçok kabuk türü üzerinde çalışırken, sadece bash'da çalışacaktır.
Isaac

@Christopher Evet, bu sondaki kaldıracak |her iki hat kullanmak kaydıyla,: printf -v mystring "%s|" * ; echo ${mystring%|}.
Isaac

7

Bu komut PERL hayranları içindir:

ls -1 | perl -l40pe0

Burada 40 uzay için sekizli ascii kodu.

-p satır satır işlenecek ve yazdırılacaktır

-l, sondaki \ n değerini sağladığımız ascii karakteriyle değiştirmeye özen gösterir.

-e PERL'i komut satırı yürütme yaptığımızı bildirmektir.

0, aslında yürütülecek komutun olmadığı anlamına gelir.

perl -e0, perl -e ile aynı ''


6

Tr için olası satırsonu karışıklığını önlemek için ls'ye -b bayrağını ekleyebiliriz:

ls -1b | tr '\n' ';'


5

Majkinetor cevabının üstüne ekleyerek, burada sondaki sınırlayıcıyı kaldırmanın yolu var (çünkü henüz cevabının altında yorum yapamıyorum):

ls -1 | awk 'ORS=","' | head -c -1

Sınırlayıcınızın saydığı kadar çok bayt çıkarın.

Bu yaklaşımı seviyorum çünkü çok karakterli sınırlayıcıları ve diğer avantajlarını kullanabilirim awk:

ls -1 | awk 'ORS=", "' | head -c -2

DÜZENLE

Peter'ın fark ettiği gibi, kafanın yerel MacOS sürümünde negatif bayt sayısı desteklenmiyor. Ancak bu kolayca düzeltilebilir.

İlk olarak yükleyin coreutils. "GNU Core Utilities, GNU işletim sisteminin temel dosya, kabuk ve metin işleme yardımcı programlarıdır."

brew install coreutils

MacOS tarafından sağlanan komutlar "g" önekiyle birlikte yüklenir. Örneğin gls.

Bunu yaptıktan sonra gheadnegatif bayt sayısı olan veya daha iyisi takma ad kullanabilirsiniz:

alias head="ghead"

Not: negatif bayt sayıları yalnızca kafanın belirli sürümlerinde desteklenir, bu nedenle bu örneğin macos üzerinde çalışmaz.
Peter

Bunu işaret ettiğiniz için teşekkürler. MacOS için bir geçici çözüm ekledim.
Aleksander Stelmaczonek

4

Sed yolu,

sed -e ':a; N; $!ba; s/\n/,/g'
  # :a         # label called 'a'
  # N          # append next line into Pattern Space (see info sed)
  # $!ba       # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
  # s/\n/,/g   # any substitution you want

Not :

Bu karmaşıktır, tüm çizgiler sed'in Desen Alanına eklendikten sonra yalnızca bir kez değiştirilir.

@ AnandRajaseka'nın yanıtı ve burada olduğu gibi diğer benzer cevaplar O (n²) 'dir, çünkü sed, Pattern Space'e her yeni satır eklendiğinde yerine geçmek zorundadır.

Karşılaştırmak,

seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
  # linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
  # quadratic, hung

3

Eğer xargs sürümü -d bayrağını destekliyorsa, bu çalışmalıdır

ls  | xargs -d, -L 1 echo

-d ayırıcı bayraktır

-D'niz yoksa aşağıdakileri deneyebilirsiniz

ls | xargs -I {} echo {}, | xargs echo

İlk xargs, bu örnekte virgül olan sınırlayıcınızı belirtmenize olanak tanır.


3
-dGNU xargs ile giriş sınırlayıcıyı belirtir, bu nedenle çalışmaz. İkinci örnek, burada bir başıboş sınırlayıcının diğer çözümleriyle aynı sorunu göstermektedir.
Thor

3
sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]

Açıklama:

-e- yürütülecek bir komutu belirtir
:a- bir etikettir
/$/N- geçerli ve (N) uzatma çizgisi için eşleşmenin kapsamını tanımlar - eşleşme başarılı olursa
s/\n/\\n/;tüm EOL'yi \n
ta;- goto etiketi a ile değiştirir

Blogumdan alındı .



2

lsbir boruya bağlandığında bir sütun çıkışı üretir, bu nedenle -1gereksizdir.

İşte join, sondaki ayırıcıyı bırakmayan yerleşik işlevi kullanan başka bir perl cevabı :

ls | perl -F'\n' -0777 -anE 'say join ",", @F'

Belirsiz -0777, programı çalıştırmadan önce perl'in tüm girdileri okumasını sağlar.

izleyen bir sınırlayıcı bırakmayan sed alternatifi

ls | sed '$!s/$/,/' | tr -d '\n'

0

ls-mçıktıyı ", "virgül ve boşlukla sınırlama seçeneğine sahiptir .

ls -m | tr -d ' ' | tr ',' ';'

trboşluk veya virgül kaldırmak için bu sonucun trborulanması, sınırlayıcıyı değiştirmek için sonucu tekrar borulamanıza izin verecektir .

benim örneğimde ayırıcıyı ayırıcı ,ile değiştiriyorum;

yerine ;ne olursa olsun sınırlayıcı bir karakter tr sadece argüman olarak geçmek dizeleri ilk karakter için hesapları beri tercih ederim.


0

Birden çok satırı tek bir satırda birleştirmek için chomp kullanabilirsiniz:

perl -e 'while (<>) {if (/ \ $ /) {chomp; } yazdır;} 'bad0> test

if cümlesi satır sonu koşulu koymak. özel karakter veya herhangi bir sınırlayıcı olabilir.


0

Sonunda eğik çizgi işleme özelliğine sahip Hızlı Perl versiyonu:

ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'

Açıklamak için:

  • perl -E: Perl'i özellik destekleriyle yürütün (diyelim ki ...)
  • say: taşıyıcı iadesi ile yazdır
  • ",", ARRAY_HERE'ye katılın: "," ile bir diziye katılın
  • map {chomp; $ _} ROWS: taşıyıcının döndürdüğü her satırdan kaldır ve sonucu döndür
  • <>: stdin, her satır bir SATIR, bir harita ile birleştiğinde her SATIR'ın bir dizisini oluşturur
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.