Sekmeleri dizinin her dosyasındaki boşluklara nasıl dönüştürebilirim?


251

Sekmeleri bir dizinin her dosyasındaki boşluklara nasıl dönüştürebilirim (muhtemelen yinelemeli olarak)?

Ayrıca, sekme başına boşluk sayısını ayarlamanın bir yolu var mı?


Dosya veya dosya adlarındaki sekmeleri değiştirmek mi istiyorsunuz?
cppcoder

3
prbunun için harika bir yardımcı programdır. Bu cevaba bakınız .
codeforester

Yanıtlar:


69

Uyarı: Bu deponuzu kıracak.

Bu irade bozuk ikili dosyalar olanlar under dahil svn, .git! Kullanmadan önce yorumları okuyun!

find . -iname '*.java' -type f -exec sed -i.orig 's/\t/ /g' {} +

Orijinal dosya olarak kaydedilir [filename].orig.

'* .Java' yerine, aradığınız dosya türünün dosya sonu ile değiştirin. Bu şekilde, ikili dosyaların yanlışlıkla bozulmasını önleyebilirsiniz.

Downsides:

  • Bir dosyanın her yerinde sekmelerin yerini alacak.
  • Bu dizinde 5GB'lık bir SQL dökümüne sahip olmanız uzun sürecektir.

12
sekmeler ve boşlukların bir karışımı olan görsel alan için bu yaklaşım yanlış genişleme sağlar.
pizza

7
Ben de sadece .php dosyaları bulmak gibi bir dosya eşleştirici eklemek istiyorum ./ -iname "* .php" -tipi f -exec sed -i 's / \ t / / g' {} \;
Daniel Luca CleanUnicorn

98
SED KULLANMAYIN! Bir dizede gömülü bir sekme varsa, kodunuzu yönetebilirsiniz. Genişletme komutunun işleyişi buydu . Kullanın expand.
David W.

5
@DavidW. Sadece satırın başından sekmeleri değiştirmek için bu komutu güncelleyeceğim. find ./ -type f -exec sed -i 's/^\t/####/g' {} \;. Ama genişlet komutunun farkında değildim - çok kullanışlı!
Martin Konecny

29
KULLANMAYIN! Bu cevap aynı zamanda yerel git depomu da mahvetti. Karışık sekmeler ve boşluklar içeren dosyalarınız varsa # 's dizileri ekleyecektir. Bunun yerine Gene'nin cevabını veya Doge'ın yorumunu kullanın.
kukla

344

İle basit değiştirme sedtamam ama mümkün olan en iyi çözüm değil. Sekmeler arasında "fazladan" boşluk varsa, ikame edildikten sonra hala orada olurlar, böylece kenar boşlukları düzensizleşir. Satırların ortasında genişletilen sekmeler de düzgün çalışmaz. Yerine bash, diyebiliriz

find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;

expandgeçerli dizin ağacındaki her Java dosyasına uygulanır . -nameBaşka dosya türlerini hedefliyorsanız argümanı kaldırın / değiştirin . Yorumlardan biri olarak, -namezayıf, joker karakteri kaldırırken veya kullanırken çok dikkatli olun . Depoyu ve diğer gizli dosyaları niyet olmadan kolayca gizleyebilirsiniz. Bu yüzden orijinal cevap şunları içeriyordu:

Bir şeyler ters gittiğinde böyle bir şey denemeden önce daima ağacın yedek bir kopyasını almalısınız.


2
@JeffreyMartinez Harika bir soru. gniourf_gniourf 11 Kasım'da orijinal cevabımı düzenledi ve doğru kullanımı bilmeme konusunda aşağılayıcı açıklamalar yaptı {}. $0Ne zaman -ckullanıldığını bilmiyor gibi görünüyor . Daha sonra dimo414, dönüşüm dizinindeki bir temp'i kullanmamdan farklı bir bağlama noktasındaysa /tmpdaha yavaş olacak şekilde değiştirildi /tmp. Maalesef $0teklifinizi test edecek bir Linux kutum yok. Ama bence haklısın.
Gene

1
@Gene, açıklama için teşekkürler, yığın akışı gibi geliyor tamam: s. Ben de olsa, ben * .java 'düzgün kaçmak için' * .java 'etrafında tırnak kullanmak zorunda kalacağım.
Jeffrey Martinez

2
Herhangi bir kişide bulmadan 'bilinmeyen birincil veya operatör' hatası varsa, işte bunu düzelten tam komut:find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Doge

4
Kullanımdan eğer: Ben bu nedenle bu benim, eskisi gibi bu cevap yeterli sayıda yorum yok olduğunu sanıyordum spongegelen joeyh.name/code/moreutils yazabilirsinizfind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
tokland

8
Aptal olma ve kullanma find . -name '*', sadece yerel git repo'yu yok ettim
Gautam

193

Komut satırı aracını deneyin expand.

expand -i -t 4 input | sponge output

nerede

  • -i her satırda yalnızca önde gelen sekmeleri genişletmek için kullanılır;
  • -t 4 her sekmenin 4 boşluk karakterine dönüştürüleceği anlamına gelir (varsayılan olarak 8).
  • spongedan moreutilspaketin kaçındığını ve giriş dosyasını temizleyerek .

Son olarak, Homebrew ( ) ile gexpandkurduktan sonra OSX'te kullanabilirsiniz .coreutilsbrew install coreutils



32
Her satırdaki yalnızca önde gelen sekmeleri değiştirmek -iiçin expandadresine geçmelisiniz . Bu, kodun bir parçası olabilecek sekmelerin değiştirilmesini önlemeye yardımcı olur.
Quolonel Soruları

10
bir dizindeki her dosya için özyinelemeye ne dersiniz?
ahnbizcad

4
Bunu her kullanmaya çalıştığımda, dosyaların bazılarını (genellikle tümünü) kapatır. : \
ThorSummoner

5
@ThorSummoner: bash ile inputaynı dosya, outputbaşlamadan önce içeriği hızlandırır expand. İşte böyle >çalışır.
Robert Siemer

34

En iyi bir yorum Toplama Gene'in cevap , çok iyi çözümü kullanmaktır spongegelen moreutils .

sudo apt-get install moreutils
# The complete one-liner:
find ./ -iname '*.java' -type f -exec bash -c 'expand -t 4 "$0" | sponge "$0"' {} \;

Açıklama:

  • ./ geçerli dizinden yinelemeli olarak arama yapıyor
  • -inameBir vaka duyarsız maçı (hem içindir *.javave *.JAVAsever)
  • type -f yalnızca normal dosyaları bulur (dizin, ikili dosya veya simge bağlantısı yoktur)
  • -exec bash -c her dosya adı için alt kabukta aşağıdaki komutları yürütebilir, {}
  • expand -t 4 tüm SEKMELER'i 4 boşluğa genişletir
  • spongestandart girişi (itibaren expand) ıslatın ve bir dosyaya (aynı olan) yazın *.

NOT : * Basit bir dosya yönlendirmesi ( > "$0") burada çalışmaz çünkü dosyanın üzerine çok erken yazılır .

Avantajı : Tüm orijinal dosya izinleri korunur ve ara tmpdosyalar kullanılmaz.


2
TIL: Linux'u 15 yıl kullandıktan sonra muhteşem sünger komutu. İnternetten gizemli şövalye teşekkür ederim.
sscarduzio

19

Ters eğik çizgiden kaçın sed.

Linux'ta:

  • Tüm sekmeleri tüm * .txt dosyalarında 1 tire ile değiştirin:

    sed -i $'s/\t/-/g' *.txt
  • Tüm * .txt dosyalarında tüm sekmeleri yerinde 1 boşlukla değiştirin:

    sed -i $'s/\t/ /g' *.txt
  • Tüm * .txt dosyalarında tüm sekmeleri yerinde 4 boşlukla değiştirin:

    sed -i $'s/\t/    /g' *.txt

Mac'te:

  • Tüm * .txt dosyalarında tüm sekmeleri yerinde 4 boşlukla değiştirin:

    sed -i '' $'s/\t/    /g' *.txt

2
@ Машаsed -i '' $'s/\t/ /g' $(find . -name "*.txt")
xyzale

Bu cevap en basit gibi görünüyor.
Yan King Yin

6

Genel olarak kullanılabilir prkomutu kullanabilirsiniz (kılavuz sayfa burada ). Örneğin, sekmeleri dört boşluğa dönüştürmek için şunu yapın:

pr -t -e=4 file > file.expanded
  • -t başlıkları bastırır
  • -e=numsekmeleri numboşluklara genişletir

İkili dosyaları atlarken dizin ağacındaki tüm dosyaları özyinelemeli olarak dönüştürmek için:

#!/bin/bash
num=4
shopt -s globstar nullglob
for f in **/*; do
  [[ -f "$f" ]]   || continue # skip if not a regular file
  ! grep -qI "$f" && continue # skip binary files
  pr -t -e=$num "$f" > "$f.expanded.$$" && mv "$f.expanded.$$" "$f"
done

İkili dosyaları atlamanın mantığı bu yayındandır .

NOT:

  1. Bunu yapmak git veya svn deposunda tehlikeli olabilir
  2. Dize değişmezlerine katıştırılmış sekmeleri olan kod dosyalarınız varsa bu doğru çözüm değildir

1
Her expandikisinin de POSIX olması avantajı var mı? Örneğin, satır içi değiştirme seçeneği var mı? Git güvenliği
şurada

5

Sekmeleri bir dizinin her dosyasındaki boşluklara nasıl dönüştürebilirim (muhtemelen yinelemeli olarak)?

Bu genellikle istediğiniz şey değildir .

Png resimleri için bunu yapmak ister misiniz? PDF dosyaları? .Git dizini? Sizin Makefile( sekmeleri gerektiren )? 5GB'lık bir SQL dökümü mü?

Teorik olarak, findkullandığınız herhangi bir şeye veya başka herhangi bir şeye dışlama seçenekleri sunabilirsiniz ; ancak bu kırılgandır ve diğer ikili dosyaları ekler eklemez kırılır.

İstediğiniz, en azından:

  1. Belirli bir boyuttaki dosyaları atla.
  2. NULL baytının olup olmadığını kontrol ederek bir dosyanın ikili olup olmadığını tespit edin.
  3. Sekmeleri yalnızca dosyanın başlangıcında değiştirin ( expandbunu yapar, sed yapmaz).

Bildiğim kadarıyla, bunu yapabilen bir "standart" Unix yardımcı programı yoktur ve bir kabuk bir astar ile yapmak çok kolay değildir, bu yüzden bir komut dosyası gereklidir.

Bir süre önce tam olarak bunu yapan sanitize_files adlı küçük bir senaryo oluşturdum . Aynı zamanda değiştirilmesi gibi bazı diğer ortak şeyler düzeltir \r\nile \n, bir sondaki ekleyerek \nvb

Aşağıdaki ekstra özellikler ve komut satırı bağımsız değişkenleri olmadan basitleştirilmiş bir komut dosyası bulabilirsiniz , ancak bu komuttan daha fazla hata düzeltmesi ve diğer güncellemeleri alma olasılığı daha yüksek olduğundan yukarıdaki komut dosyasını kullanmanızı öneririz.

Ayrıca, buradaki diğer cevapların bazılarına yanıt olarak, kabuk globbing kullanmanın bunu yapmanın sağlam bir yolu olmadığını belirtmek isterim , çünkü er ya da geç sığacak daha fazla dosyaya sahip olacaksınız ARG_MAX(modern Linux sistemleri 128k, bu çok görünebilir, ancak er ya da geç yeterli değildir ).


#!/usr/bin/env python
#
# http://code.arp242.net/sanitize_files
#

import os, re, sys


def is_binary(data):
    return data.find(b'\000') >= 0


def should_ignore(path):
    keep = [
        # VCS systems
        '.git/', '.hg/' '.svn/' 'CVS/',

        # These files have significant whitespace/tabs, and cannot be edited
        # safely
        # TODO: there are probably more of these files..
        'Makefile', 'BSDmakefile', 'GNUmakefile', 'Gemfile.lock'
    ]

    for k in keep:
        if '/%s' % k in path:
            return True
    return False


def run(files):
    indent_find = b'\t'
    indent_replace = b'    ' * indent_width

    for f in files:
        if should_ignore(f):
            print('Ignoring %s' % f)
            continue

        try:
            size = os.stat(f).st_size
        # Unresolvable symlink, just ignore those
        except FileNotFoundError as exc:
            print('%s is unresolvable, skipping (%s)' % (f, exc))
            continue

        if size == 0: continue
        if size > 1024 ** 2:
            print("Skipping `%s' because it's over 1MiB" % f)
            continue

        try:
            data = open(f, 'rb').read()
        except (OSError, PermissionError) as exc:
            print("Error: Unable to read `%s': %s" % (f, exc))
            continue

        if is_binary(data):
            print("Skipping `%s' because it looks binary" % f)
            continue

        data = data.split(b'\n')

        fixed_indent = False
        for i, line in enumerate(data):
            # Fix indentation
            repl_count = 0
            while line.startswith(indent_find):
                fixed_indent = True
                repl_count += 1
                line = line.replace(indent_find, b'', 1)

            if repl_count > 0:
                line = indent_replace * repl_count + line

        data = list(filter(lambda x: x is not None, data))

        try:
            open(f, 'wb').write(b'\n'.join(data))
        except (OSError, PermissionError) as exc:
            print("Error: Unable to write to `%s': %s" % (f, exc))


if __name__ == '__main__':
    allfiles = []
    for root, dirs, files in os.walk(os.getcwd()):
        for f in files:
            p = '%s/%s' % (root, f)
            if do_add:
                allfiles.append(p)

    run(allfiles)


5

Yinelemeli uygulama için yukarıdaki "find" örneğini seviyorum. Yinelemeli olmayacak şekilde uyarlamak için, yalnızca geçerli dizindeki joker karakterle eşleşen dosyaları değiştirmek için kabuk glob genişletmesi küçük miktarlardaki dosyalar için yeterli olabilir:

ls *.java | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh -v

Çalıştığından emin olduktan sonra sessiz olmasını istiyorsanız -v, shkomutun sonunda bırakın .

Tabii ki ilk komutta herhangi bir dosya grubunu seçebilirsiniz. Örneğin, yalnızca belirli bir alt dizini (veya dizinleri) aşağıdaki gibi denetimli bir biçimde listeleyin:

ls mod/*/*.php | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh

Ya da find (1) 'i bazı derinlik parametrelerinin kombinasyonu ile çalıştırın:

find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh

1
Kabuk globbing er ya da geç kırılacaktır, çünkü toplam dosya adı miktarı sadece ARG_MAXuzun olabilir. Bu, Linux sistemlerinde 128 bin, ancak bu sınırı kabuk globbing'e güvenmemek için yeterince kez karşılaştım.
Martin Tournoij

1
Onları gerçekten uyarlamanıza gerek yok. findsöylenebilir -maxdepth 1ve sadece değiştirilen dizinin girişlerini işler, tüm ağacı değil.
ShadowRanger

4

astyleKarma sekmeler ve boşluklar bulduktan sonra tüm C / C ++ kodumu yeniden girintili olarak kullandım . Ayrıca, isterseniz belirli bir küme ayracı stilini zorlama seçeneklerine de sahiptir.


4

Bunun için kullanılabilir vim:

find -type f \( -name '*.css' -o -name '*.html' -o -name '*.js' -o -name '*.php' \) -execdir vim -c retab -c wq {} \;

Carpetsmoker'in belirttiği gibi, vimayarlarınıza göre yeniden ayarlanacaktır. Ve varsa dosyalarda modelinler. Ayrıca, sekmeleri yalnızca satırların başında değil. Bu genellikle istediğiniz şey değildir. Örneğin, sekmeler içeren değişmez değerleriniz olabilir.


:retabdosyadaki tüm sekmeleri değiştirir, başlangıçtaki sekmeleri değiştirmez. aynı zamanda sizin :tabstopve :expandtabayarlarınızın vimrc veya modelinde ne olduğuna bağlıdır , bu yüzden bu hiç işe yaramayabilir.
Martin Tournoij

@Carpetsmoker Satırların başında sekmeler hakkında iyi bir nokta. Buradaki çözümlerden herhangi biri bu durumu ele alıyor mu? tabstopVe expandtabayarlarına gelince , kullanıyorsanız bu işe yarayacaktır vim. Dosyalarda mod satırları yoksa.
x-yuri

@ x-yuri iyi bir soru, ama genellikle tartışmalı. Çoğu kişi gerçekte sekme kullanmaz.
Ricardo Cruz

4

Benim tavsiyem:

find . -name '*.lua' -exec ex '+%s/\t/  /g' -cwq {} \;

Yorumlar:

  1. Yerinde düzenleme kullanın. Yedekleri bir VCS'de tutun. * .Orig dosyası üretmenize gerek yoktur. Her durumda, beklendiği gibi çalıştığından emin olmak için sonucu son taahhüdünüze göre dağıtmak iyi bir uygulamadır.
  2. sedbir akış düzenleyicisidir. exYerinde düzenleme için kullanın . Bu, üst yanıtta olduğu gibi her değiştirme için ekstra geçici dosyalar oluşturmayı ve kabukları oluşturmayı önler .
  3. UYARI: Bu, yalnızca girinti için kullanılanlarla değil, tüm sekmelerle karıştırır. Ayrıca sekmelere bağlam farkında değiştirme yapmaz. Bu benim kullanım durumum için yeterliydi. Ama sizin için kabul edilebilir olmayabilir.
  4. DÜZENLE: Bunun find|xargsyerine bu cevabın önceki bir sürümü kullanıldı find -exec. @ Gniourf-gniourf tarafından işaret edildiği gibi, bu dosya adlarında boşluklar, tırnak işaretleri ve kontrol karakterleriyle ilgili sorunlara yol açar. Wheeler .

exher Unix sisteminde mevcut olmayabilir. Bunun yerine vi -ekoymak daha fazla makinede işe yarayabilir. Ayrıca, normal ifadeniz herhangi bir sayıda başlangıç ​​sekmesi karakterini iki boşlukla değiştirir. +%s/\t/ /gÇok düzeyli girinti yok etmek için normal ifadeyi değiştirin . Ancak bu, girinti için kullanılmayan sekme karakterlerini de etkiler.
Lukas Schmelzeisen

ex POSIX [1] 'in bir parçası olduğu için mevcut olmalıdır. Çok seviyeli girinti hakkında iyi bir nokta. Aslında kullanmıştı /\t/ /benim dosyalar üzerinde varyantı, ama seçti /\t\+//olmayan girinti çıkıntıları kırmak değil. Çoklu girintili sorunları kaçırdınız! Cevabı Güncelleme. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSO
Heinrich Hartmann

2
xargsBu şekilde kullanmak işe yaramaz, verimsiz ve kırılmıştır (boşluk veya tırnak içeren dosya adlarını düşünün). Neden kullanmayın find'ın -execyerine anahtarını?
gniourf_gniourf

Boşlukları ve tırnak işaretleri içeren dosya adlarının bozulduğunu iddia ediyorum; ) Desteklemeniz gerekiyorsa: -print0/ xargs bulma seçenekleri. Ben xargs sevdim -execçünkü: a) Endişelerin ayrılması b) GNU paralel ile daha kolay değiştirilebilir.
Heinrich Hartmann

@Gniourf_gniourf yorum ekleyerek güncellendi.
Heinrich Hartmann

4

Bir dizindeki tüm Java dosyalarını özyinelemeli olarak sekme yerine 4 boşluk kullanmak üzere dönüştürmek için:

find . -type f -name *.java -exec bash -c 'expand -t 4 {} > /tmp/stuff;mv /tmp/stuff {}' \;

Nasıl bu cevabı farklıdır bu 4 yıl önce gönderildiği?
PP

2
Cevabınız da öyle. Aslında, bu Gene'nin cevabının kalitesiz bir versiyonudur: 1) Gene'nin cevabı aynı isimdeki dizinlerle ilgilenir. 2) Genişletme başarısız olursa hareket etmez .
PP

4

Bunun için paketle findbirlikte kullanabilirsiniz tabs-to-spaces.

İlk olarak, yükleyin tabs-to-spaces

npm install -g tabs-to-spaces

sonra bu komutu projenizin kök dizininden çalıştırın;

find . -name '*' -exec t2s --spaces 2 {} \;

Bu, her tabkarakterdeki her karakteri 2 ile değiştirir spaces.


3

Hiç vücuttan bahsedilmedi rplmi? Rpl kullanarak herhangi bir dizeyi değiştirebilirsiniz. Sekmeleri boşluklara dönüştürmek için,

rpl -R -e "\t" "    "  .

Çok basit.


1
Bu, depomdaki tüm ikili dosyaları bozdu.
Aaron Franke

1
Mükemmel bir komut, ancak yukarıda belirtildiği gibi özyinelemeli ve klasördeki tüm dosyalar için potansiyel olarak tehlikeli. Doğru klasörde oturduğunuzdan emin olmak için --dry-run seçeneğini "her ihtimale karşı" eklerdim.
MortimerCat

2

Kullanımı expanddiğer yanıtlar önerilen tek başına bu görev için en mantıklı yaklaşım gibi görünüyor.

Bununla birlikte, diğer bazı modifikasyonları yapmak isteyebileceğiniz durumunda Bash ve Awk ile de yapılabilir.

Bash 4.0 veya üstünü kullanıyorsanız, shopt yerleşkesiglobstar ile özyinelemeli arama yapmak için kullanılabilir **.

GNU Awk sürüm 4.1 veya üstü ile sed gibi "inplace" dosya değişiklikleri yapılabilir:

shopt -s globstar
gawk -i inplace '{gsub("\t","    ")}1' **/*.ext

Sekme başına boşluk sayısını ayarlamak istiyorsanız:

gawk -i inplace -v n=4 'BEGIN{for(i=1;i<=n;i++) c=c" "}{gsub("\t",c)}1' **/*.ext

2

Sabit sekmeleri düz metin dosyalarındaki yumuşak sekmelere özyineli olarak dönüştürmek için aşağıdaki komut dosyasını indirin ve çalıştırın.

Komut dosyasını düz metin dosyalarını içeren klasörün içinden yürütün.

#!/bin/bash

find . -type f -and -not -path './.git/*' -exec grep -Iq . {} \; -and -print | while read -r file; do {
    echo "Converting... "$file"";
    data=$(expand --initial -t 4 "$file");
    rm "$file";
    echo "$data" > "$file";
}; done;

2

Git veri havuzu dostu yöntem

git-tab-to-space() (
  d="$(mktemp -d)"
  git grep --cached -Il '' | grep -E "${1:-.}" | \
    xargs -I'{}' bash -c '\
    f="${1}/f" \
    && expand -t 4 "$0" > "$f" && \
    chmod --reference="$0" "$f" && \
    mv "$f" "$0"' \
    '{}' "$d" \
  ;
  rmdir "$d"
)

Geçerli dizinin altındaki tüm dosyalara göre hareket et:

git-tab-to-space

Yalnızca C veya C ++ dosyalarında kullanılabilir:

git-tab-to-space '\.(c|h)(|pp)$'

Bunu büyük olasılıkla sekmeler gerektiren can sıkıcı Makefiles nedeniyle istersiniz.

Komut git grep --cached -Il '':

  • yalnızca izlenen dosyaları listeler, böylece içindeki hiçbir şey .git
  • dizinleri, ikili dosyaları (bozuk) ve simgeleri (normal dosyalara dönüştürülür) hariç tutar

açıklandığı gibi: Git deposundaki tüm metin (ikili olmayan) dosyalar nasıl listelenir?

chmod --referencedosya izinlerini değiştirmez: /unix/20645/clone-ownership-and-permissions-from-another-file Maalesef kısa bir POSIX alternatifi bulamıyorum .

Kod tabanınız, dizelerde işlevsel ham sekmelere izin verme konusunda çılgın bir fikre sahipse, şunu kullanın:

expand -i

: ve ardından eğlenceli ile listeleyebilirsiniz satır sekmeler teker teker olmayan tüm başlamasından üzerinden gidiyor olması o sekmeler için git grep mümkün mü?

Ubuntu 18.04'te test edildi.


-1

Sekmeleri yalnızca ".lua" dosyalarındaki boşluğa dönüştürme [sekmeler -> 2 boşluk]

find . -iname "*.lua" -exec sed -i "s#\t#  #g" '{}' \;

Açıkçası, bir sekmenin genişlediği alan miktarı bağlama bağlıdır. Bu nedenle sed, görev için tamamen uygunsuz bir araçtır.
Sven

?? @Sven, sed komutum, expand komutunun yaptığı aynı şeyi yapıyor ( expand -t 4 input >output)
Makah

3
Tabii ki değil. expand -t 4sekmeyi olması a\tbgerektiği gibi 3 boşluğa ve aa\tb2 boşluğa genişletir . expandsekmenin içeriğini dikkate alır, bağlamdan sedbağımsız olarak sekmeyi belirttiğiniz alan miktarıyla değiştirmez ve değiştirir.
Sven

-1

Vim-way kullanın:

$ ex +'bufdo retab' -cxa **/*.*
  • Yedekleme yapın! Yukarıdaki komutu yürütmeden önce, ikili dosyalarınızı bozabileceğinden.
  • Özyineleme için globstar( **) kullanmak için, ile etkinleştirin shopt -s globstar.
  • Belirli bir dosya türünü belirtmek için, örneğin kullanın: **/*.c.

Sekmeyi değiştirmek için ekleyin +'set ts=2'.

Ancak aşağı tarafı dizelerin içindeki sekmelerin yerini alabilmesidir .

Yani biraz daha iyi bir çözüm için (ikame kullanarak) şunu deneyin:

$ ex -s +'bufdo %s/^\t\+/  /ge' -cxa **/*.*

Veya exeditör + expandyardımcı programını kullanarak :

$ ex -s +'bufdo!%!expand -t2' -cxa **/*.*

Sondaki boşluklar için bkz: Birden çok dosya için sondaki boşluklar nasıl kaldırılır?


Aşağıdaki işlevi ekleyebilirsiniz .bash_profile:

# Convert tabs to spaces.
# Usage: retab *.*
# See: https://stackoverflow.com/q/11094383/55075
retab() {
  ex +'set ts=2' +'bufdo retab' -cxa $*
}

Ben sadece sizin değil, bu konudaki birçok cevapları düşürdüm Nedenler: :retabhiç işe yaramayabilir , kabuk globbing bu tür bir şey için kötü bir çözümdür , :skomutunuz herhangi bir sekme miktarını 2 boşlukla değiştirecektir (ki neredeyse asla istemiyorum), sadece bir :!expandişlemi yürütmek için eski başlamak aptalca ...
Martin Tournoij

... ve tüm çözümleriniz ikili dosyaları ve benzerlerini (.png dosyaları, .pdf dosyaları vb. gibi)
hızlandıracaktır

Açıkçası bu dokümantasyon için korkunç bir öneri - bunu anlayabilmek için bir dizi oldukça opak sözdizimi ve semantik konularla yakından tanışmak gerekiyor.
Josip Rodin
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.