Bagaimana saya bisa mengonversi tab menjadi spasi di setiap file direktori?

251

Bagaimana saya bisa mengonversi tab menjadi spasi di setiap file direktori (mungkin secara rekursif)?

Juga, apakah ada cara mengatur jumlah spasi per tab?

cnd
sumber
Anda ingin mengganti tab di file atau nama file?
cppcoder
3
pradalah utilitas luar biasa untuk ini. Lihat jawaban ini .
codeforester

Jawaban:

69

Peringatan: Ini akan merusak repo Anda.

Ini akan merusak file biner , termasuk di bawah mereka svn, .git! Baca komentar sebelum menggunakan!

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

File asli disimpan sebagai [filename].orig.

Ganti '* .java' dengan akhiran file dari jenis file yang Anda cari. Dengan cara ini Anda dapat mencegah kerusakan file biner secara tidak sengaja.

Kerugian:

  • Akan mengganti tab di mana saja di file.
  • Akan memakan waktu lama jika Anda memiliki dump SQL 5GB di direktori ini.
Martin Beckett
sumber
12
untuk ruang visual yang merupakan campuran tab dan spasi, pendekatan ini memberikan ekspansi yang salah.
pizza
7
Saya juga akan menambahkan pencocokan file seperti misalnya hanya untuk menemukan file .php ./ -iname "* .php" -type f -exec sed -i 's / \ t / / g' {} \;
Daniel Luca CleanUnicorn
98
JANGAN GUNAKAN SED! Jika ada tab yang disematkan dalam sebuah string, Anda mungkin berakhir menyusun kode Anda. Inilah yang perintah memperluas dimaksudkan untuk menangani. Gunakan expand.
David W.
5
@ DavidW. Saya hanya akan memperbarui perintah ini untuk hanya mengganti tab dari awal baris. find ./ -type f -exec sed -i 's/^\t/####/g' {} \;. Tapi saya tidak menyadari perintah memperluas - sangat berguna!
Martin Konecny
29
JANGAN GUNAKAN! Jawaban ini juga hanya merusak repositori git lokal saya. Jika Anda memiliki file yang berisi tab dan spasi campuran, itu akan menyisipkan urutan # 's. Gunakan jawaban oleh Gene atau komentar oleh Doge sebagai gantinya.
boneka
344

Penggantian sederhana dengan sedtidak apa-apa tapi bukan solusi terbaik. Jika ada ruang "ekstra" di antara tab, mereka akan tetap ada setelah penggantian, sehingga margin akan menjadi acak-acakan. Tab yang diperluas di tengah garis juga tidak akan berfungsi dengan benar. Di bash, kita bisa mengatakan sebaliknya

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

untuk diterapkan expandke setiap file Java di pohon direktori saat ini. Hapus / ganti -nameargumen jika Anda menargetkan beberapa jenis file lainnya. Seperti yang disebutkan dalam salah satu komentar, berhati-hatilah saat mengeluarkan -nameatau menggunakan kartu pengganti yang lemah. Anda dapat dengan mudah menerima repositori dan file tersembunyi lainnya tanpa sengaja. Inilah sebabnya mengapa jawaban asli termasuk ini:

Anda harus selalu membuat salinan cadangan pohon sebelum mencoba sesuatu seperti ini jika terjadi kesalahan.

Gene
sumber
2
@ JeffreyMartinez Pertanyaan bagus. gniourf_gniourf mengedit jawaban asli saya pada 11 November dan membuat komentar meremehkan tentang tidak mengetahui cara yang tepat untuk digunakan {}. Sepertinya dia tidak tahu $0kapan -cdigunakan. Kemudian dimo414 berubah dari penggunaan temp saya di direktori konversi menjadi /tmp, yang akan jauh lebih lambat jika /tmpberada pada titik mount yang berbeda. Sayangnya saya tidak memiliki kotak Linux yang tersedia untuk menguji $0proposal Anda . Tapi saya pikir Anda benar.
Gene
1
@ Gen, terima kasih atas klarifikasi, yang terdengar seperti stackoverflow, oke: p. Sementara saya melakukannya, saya akan menambahkan saya harus menggunakan tanda kutip di sekitar '* .java' untuk melarikan diri dari * .java.
Jeffrey Martinez
2
Jika ada yang mengalami kesalahan 'primer atau operator tidak dikenal' dari find, maka di sini adalah perintah lengkap yang akan memperbaikinya:find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Doge
4
Saya pikir jawaban ini tidak memiliki komentar yang cukup, jadi ini milik saya: jika gunakan spongedari joeyh.name/code/moreutils , Anda dapat menulisfind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
tokland
8
Jangan bodoh dan gunakan find . -name '*', saya baru saja menghancurkan git repo lokal saya
Gautam
193

Coba alat baris perintah expand.

expand -i -t 4 input | sponge output

dimana

  • -i digunakan untuk memperluas hanya tab utama di setiap baris;
  • -t 4 berarti bahwa setiap tab akan dikonversi menjadi 4 spasi spasi (8 secara default).
  • spongeberasal dari moreutilspaket, dan menghindari membersihkan file input .

Akhirnya, Anda dapat menggunakan gexpandOSX, setelah menginstal coreutilsdengan Homebrew ( brew install coreutils).

kev
sumber
5
Ini salah satu dari GNU_Core_Utilities
kev
32
Anda harus beralih -ike expandhanya mengganti tab terkemuka di setiap baris. Ini membantu menghindari penggantian tab yang mungkin menjadi bagian dari kode.
Pertanyaan Quolonel
10
bagaimana dengan setiap file dalam direktori secara rekursif?
ahnbizcad
4
Setiap kali saya mencoba menggunakan ini, itu kosong beberapa (biasanya semua) file. : \
ThorSummoner
5
@ThorSummoner: if inputadalah file yang sama outputdengan bash clobbers konten bahkan sebelum memulai expand. Beginilah cara >kerjanya.
Robert Siemer
34

Mengumpulkan komentar terbaik dari jawaban Gene , solusi terbaik sejauh ini, adalah dengan menggunakan spongedari moreutils .

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

Penjelasan:

  • ./ secara rekursif mencari dari direktori saat ini
  • -inameadalah pencocokan huruf besar-kecil (untuk keduanya *.javadan *.JAVAsuka)
  • type -f hanya menemukan file biasa (tidak ada direktori, binari atau symlink)
  • -exec bash -c menjalankan perintah berikut dalam subkulit untuk setiap nama file, {}
  • expand -t 4 perluas semua TAB menjadi 4 ruang
  • spongemenyerap input standar (dari expand) dan menulis ke file (yang sama) *.

CATATAN : * Pengalihan file sederhana ( > "$0") tidak akan berfungsi di sini karena akan menimpa file terlalu cepat .

Keuntungan : Semua izin file asli dipertahankan dan tidak ada tmpfile perantara yang digunakan.

not2qubit
sumber
2
TIL: perintah spons yang luar biasa, setelah 15 tahun menggunakan Linux. Terima kasih ksatria misterius dari internet.
sscarduzio
19

Gunakan garis miring terbalik sed.

Di linux:

  • Ganti semua tab dengan 1 tanda hubung di tempat, di semua file * .txt:

    sed -i $'s/\t/-/g' *.txt
  • Ganti semua tab dengan 1 spasi di tempat, di semua file * .txt:

    sed -i $'s/\t/ /g' *.txt
  • Ganti semua tab dengan 4 spasi di tempat, di semua file * .txt:

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

Di mac:

  • Ganti semua tab dengan 4 spasi di tempat, di semua file * .txt:

    sed -i '' $'s/\t/    /g' *.txt
e9t
sumber
2
@ Машаsed -i '' $'s/\t/ /g' $(find . -name "*.txt")
xyzale
Jawaban ini tampaknya paling sederhana.
Yan King Yin
6

Anda dapat menggunakan prperintah yang tersedia secara umum (halaman manual di sini ). Misalnya, untuk mengonversi tab menjadi empat spasi, lakukan ini:

pr -t -e=4 file > file.expanded
  • -t menekan tajuk
  • -e=numperluas tab ke numspasi

Untuk mengonversi semua file di pohon direktori secara rekursif, sambil melewatkan file biner:

#!/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

Logika untuk melewatkan file biner adalah dari posting ini .

CATATAN:

  1. Melakukan ini bisa berbahaya dalam repo git atau svn
  2. Ini bukan solusi yang tepat jika Anda memiliki file kode yang memiliki tab yang tertanam dalam string literal
codeforester
sumber
1
Adakah keuntungan lebih dari expandmengingat bahwa keduanya POSIX? Misalnya apakah ada opsi perubahan sebaris? Git safety at: stackoverflow.com/a/52136507/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功
5

Bagaimana saya bisa mengonversi tab menjadi spasi di setiap file direktori (mungkin secara rekursif)?

Ini biasanya bukan yang Anda inginkan.

Apakah Anda ingin melakukan ini untuk gambar png? File PDF? Direktori .git? Anda Makefile(yang membutuhkan tab)? Dump SQL 5GB?

Secara teori, Anda bisa meneruskan banyak opsi pengecualian ke findatau apa pun yang Anda gunakan; tetapi ini rapuh, dan akan pecah segera setelah Anda menambahkan file biner lainnya.

Yang Anda inginkan, setidaknya:

  1. Lewati file dengan ukuran tertentu.
  2. Mendeteksi jika file biner dengan memeriksa keberadaan byte NULL.
  3. Hanya ganti tab pada awal file ( expandapakah ini, sed tidak).

Sejauh yang saya tahu, tidak ada utilitas Unix "standar" yang dapat melakukan ini, dan itu tidak mudah dilakukan dengan shell one-liner, jadi diperlukan skrip.

Beberapa waktu yang lalu saya membuat skrip kecil bernama sanitize_files yang melakukan hal itu. Juga perbaikan beberapa hal umum lainnya seperti mengganti \r\ndengan \n, menambahkan Trailing \n, dll

Anda dapat menemukan skrip yang disederhanakan tanpa fitur tambahan dan argumen baris perintah di bawah ini, tetapi saya sarankan Anda menggunakan skrip di atas karena lebih mungkin untuk menerima perbaikan bug dan pembaruan lainnya daripada posting ini.

Saya juga ingin menunjukkan, dalam menanggapi beberapa jawaban lain di sini, bahwa menggunakan shell globbing bukanlah cara yang kuat untuk melakukan ini, karena cepat atau lambat Anda akan berakhir dengan lebih banyak file daripada yang akan cocok ARG_MAX(pada modern Sistem Linux 128k, yang mungkin tampak banyak, tetapi cepat atau lambat itu tidak cukup).


#!/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)
Martin Tournoij
sumber
Dalam git, pemeriksaan binernya mudah: stackoverflow.com/a/52136507/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 事件
5

Saya suka contoh "temukan" di atas untuk aplikasi rekursif. Untuk mengadaptasinya menjadi non-rekursif, hanya mengubah file di direktori saat ini yang cocok dengan wildcard, ekspansi glob shell bisa mencukupi untuk sejumlah kecil file:

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

Jika Anda ingin itu diam setelah Anda percaya bahwa itu berfungsi, cukup letakkan -vpada shperintah di akhir.

Tentu saja Anda dapat memilih set file dalam perintah pertama. Misalnya, daftar hanya subdirektori tertentu (atau direktori) dengan cara yang terkontrol seperti ini:

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

Atau pada gilirannya jalankan temukan (1) dengan beberapa kombinasi parameter kedalaman dll:

find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
drchuck
sumber
1
Shell globbing akan rusak cepat atau lambat, karena jumlah total nama file hanya ARG_MAXpanjang. Ini 128k pada sistem Linux, tetapi saya telah menemui batas ini cukup kali untuk tidak bergantung pada shell globbing.
Martin Tournoij
1
Anda tidak perlu menyesuaikannya. finddapat dikatakan -maxdepth 1, dan hanya memproses entri direktori yang sedang dimodifikasi, bukan seluruh pohon.
ShadowRanger
4

Saya digunakan astyleuntuk indentasi ulang semua kode C / C ++ saya setelah menemukan tab dan spasi campuran. Ia juga memiliki opsi untuk memaksa gaya penyangga tertentu jika Anda mau.

Theo Belaire
sumber
4

Satu dapat digunakan vimuntuk itu:

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

Seperti yang dinyatakan oleh Carpetsmoker, itu akan melakukan retab sesuai dengan vimpengaturan Anda . Dan modelines dalam file, jika ada. Juga, itu akan mengganti tab tidak hanya di awal baris. Yang bukan apa yang biasanya Anda inginkan. Misalnya, Anda mungkin memiliki literal, yang berisi tab.

x-yuri
sumber
:retabakan mengubah semua tab dalam file, bukan yang di awal. itu juga tergantung pada apa :tabstopdan :expandtabpengaturan Anda di vimrc atau modeline, jadi ini mungkin tidak berfungsi sama sekali.
Martin Tournoij
@Carpetsmoker Poin bagus tentang tab di awal baris. Apakah ada solusi di sini yang menangani kasus ini? Adapun pengaturan tabstopdan expandtab, itu akan berhasil jika Anda menggunakan vim. Kecuali jika Anda memiliki garis mode di file.
x-yuri
@ x-yuri pertanyaan bagus, tapi umumnya bisa diperdebatkan. Sebagian besar orang menggunakan bukan tab yang sebenarnya dalam literal.
Ricardo Cruz
4

Rekomendasi saya adalah menggunakan:

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

Komentar:

  1. Gunakan pengeditan di tempat. Simpan cadangan dalam VCS. Tidak perlu menghasilkan file * .orig. Praktik yang baik untuk membedakan hasilnya dengan komit terakhir Anda untuk memastikan ini bekerja seperti yang diharapkan, dalam hal apa pun.
  2. sedadalah editor aliran. Gunakan exuntuk mengedit di tempat. Ini menghindari membuat file temp tambahan dan spawning shells untuk setiap penggantian seperti pada jawaban teratas .
  3. PERINGATAN: Ini mengacaukan semua tab, tidak hanya yang digunakan untuk indentasi. Juga tidak melakukan penggantian tab sadar konteks. Ini cukup untuk kasus penggunaan saya. Tetapi mungkin tidak dapat diterima untuk Anda.
  4. EDIT: Versi sebelumnya dari jawaban ini digunakan find|xargssebagai ganti find -exec. Seperti yang ditunjukkan oleh @ gniourf-gniourf ini menyebabkan masalah dengan spasi, tanda kutip dan karakter kontrol dalam nama file cf. Wheeler .
Heinrich Hartmann
sumber
exmungkin tidak tersedia di setiap sistem Unix. Mengganti dengan vi -emungkin bekerja pada lebih banyak mesin. Juga, regex Anda menggantikan sejumlah karakter tab awal dengan dua spasi. Ganti regex dengan +%s/\t/ /gtidak merusak lekukan multi level. Namun ini juga memengaruhi karakter tab yang tidak digunakan untuk indentasi.
Lukas Schmelzeisen
ex adalah bagian dari POSIX [1] jadi harus tersedia. Poin bagus tentang multi level indendation. Saya sebenarnya telah menggunakan /\t/ /varian pada file saya, tetapi memilih untuk /\t\+//tidak merusak tab yang tidak membuat indentasi. Merindukan masalah dengan lekukan multi! Memperbarui Jawaban. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSO
Heinrich Hartmann
2
Menggunakan xargscara ini tidak berguna, tidak efisien dan rusak (pikirkan nama file yang mengandung spasi atau kutipan). Mengapa Anda tidak menggunakan find's -execberalih bukan?
gniourf_gniourf
Saya berpendapat bahwa nama file dengan spasi dan tanda kutip rusak; ) Jika Anda perlu mendukung bahwa saya akan memilih: -print0opsi untuk menemukan / xargs. Saya suka xargs -execsejak: a) Pemisahan masalah b) dapat ditukar dengan GNU paralel lebih mudah.
Heinrich Hartmann
Diperbarui menambahkan komentar @gniourf_gniourf.
Heinrich Hartmann
4

Untuk mengonversi semua file Java secara rekursif dalam direktori menggunakan 4 spasi alih-alih tab:

find . -type f -name *.java -exec bash -c 'expand -t 4 {} > /tmp/stuff;mv /tmp/stuff {}' \;
Raffi Khatchadourian
sumber
Bagaimana jawaban ini berbeda dari ini yang diposting 4 tahun yang lalu?
PP
2
Begitu juga jawaban Anda. Sebenarnya, ini adalah versi yang lebih rendah dari jawaban Gene: 1) Jawaban Gene menjaga direktori dengan nama yang sama. 2) Tidak bergerak jika ekspansi gagal.
PP
4

Anda dapat menggunakan finddengan tabs-to-spacespaket untuk ini.

Pertama, instal tabs-to-spaces

npm install -g tabs-to-spaces

kemudian, jalankan perintah ini dari direktori root proyek Anda;

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

Ini akan mengganti setiap tabkarakter dengan 2 spacesdi setiap file.

Harsh Vakharia
sumber
3

Tidak ada badan yang disebutkan rpl? Menggunakan rpl Anda dapat mengganti string apa pun. Untuk mengonversi tab menjadi spasi,

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

sangat sederhana.

PeopleMoutainPeopleSea
sumber
1
Ini merusak semua file biner di repo saya.
Aaron Franke
1
Perintah yang sangat baik, tetapi berpotensi berbahaya dengan opsi rekursif dan semua file dalam folder seperti yang ditentukan di atas. Saya akan menambahkan opsi --dry-run "berjaga-jaga" untuk memastikan Anda duduk di folder yang tepat.
MortimerCat
2

Penggunaan expandseperti yang disarankan dalam jawaban lain tampaknya merupakan pendekatan yang paling logis untuk tugas ini saja.

Yang mengatakan, itu juga dapat dilakukan dengan Bash dan Awk jika Anda mungkin ingin melakukan beberapa modifikasi lain bersamanya.

Jika menggunakan Bash 4.0 atau lebih besar, shopt builtin globstar dapat digunakan untuk mencari secara rekursif **.

Dengan GNU Awk versi 4.1 atau lebih tinggi, modifikasi file seperti "inplace" dapat dibuat:

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

Jika Anda ingin mengatur jumlah spasi per tab:

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

Unduh dan jalankan skrip berikut untuk secara rekursif mengonversi tab keras menjadi tab lunak dalam file teks biasa.

Jalankan skrip dari dalam folder yang berisi file teks biasa.

#!/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;
daka
sumber
2

Metode ramah repositori

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"
)

Bertindak pada semua file di bawah direktori saat ini:

git-tab-to-space

Bertindak hanya pada file C atau C ++:

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

Anda mungkin menginginkan ini terutama karena Makefile yang mengganggu yang memerlukan tab.

Perintah git grep --cached -Il '' :

  • daftar hanya file yang dilacak, jadi tidak ada di dalamnya .git
  • mengecualikan direktori, file biner (akan rusak), dan symlink (akan dikonversi ke file biasa)

seperti yang dijelaskan di: Bagaimana cara mendaftar semua file teks (non-biner) dalam repositori git?

chmod --referencemembuat izin file tidak berubah: /unix/20645/clone-ownership-and-permissions-from-another-file Sayangnya saya tidak dapat menemukan alternatif POSIX yang ringkas .

Jika basis kode Anda memiliki ide gila untuk mengizinkan tab mentah fungsional dalam string, gunakan:

expand -i

dan kemudian bersenang-senang memeriksa semua tab awal yang tidak dimulai satu per satu, yang dapat Anda daftarkan: Apakah mungkin untuk mendapatkan grep untuk tab?

Diuji pada Ubuntu 18.04.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
-1

Mengonversi tab menjadi spasi hanya dalam file ".lua" [tab -> 2 spasi]

find . -iname "*.lua" -exec sed -i "s#\t#  #g" '{}' \;
Makah
sumber
Jelas, jumlah ruang yang diperlebar pada sebuah tab tergantung pada konteksnya. Dengan demikian, sed adalah alat yang sama sekali tidak pantas untuk tugas tersebut.
Sven
?? @ Bahkan, perintah sed saya melakukan hal yang sama dengan memperluas perintah ( expand -t 4 input >output)
Makah
3
Tentu saja tidak. expand -t 4akan memperluas tab a\tbke 3 spasi dan tab aa\tbke 2 spasi, seperti yang seharusnya. expandmempertimbangkan konteks tab, sedtidak dan akan mengganti tab dengan jumlah spasi yang Anda tentukan, terlepas dari konteksnya.
Sven
-1

Gunakan vim-way:

$ ex +'bufdo retab' -cxa **/*.*
  • Buat cadangan! sebelum menjalankan perintah di atas, karena dapat merusak file biner Anda.
  • Untuk menggunakan globstar( **) untuk rekursi, aktifkan oleh shopt -s globstar.
  • Untuk menentukan jenis file tertentu, gunakan misalnya: **/*.c.

Untuk memodifikasi tabstop, tambahkan +'set ts=2'.

Namun sisi buruknya adalah ia dapat mengganti tab di dalam string .

Jadi untuk solusi yang sedikit lebih baik (dengan menggunakan substitusi), coba:

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

Atau dengan menggunakan exeditor + expandutility:

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

Untuk spasi tambahan, lihat: Bagaimana menghapus spasi spasi tambahan untuk banyak file?


Anda dapat menambahkan fungsi berikut ke .bash_profile:

# Convert tabs to spaces.
# Usage: retab *.*
# See: https://stackoverflow.com/q/11094383/55075
retab() {
  ex +'set ts=2' +'bufdo retab' -cxa $*
}
kenorb
sumber
Aku downvoted banyak jawaban di thread ini, tidak hanya Anda ;-) Alasan adalah: :retabmungkin tidak bekerja sama sekali , shell globbing adalah solusi yang buruk untuk hal semacam ini , Anda :sperintah akan menggantikan setiap jumlah tab dengan 2 spasi (yang Anda hampir tidak pernah mau), memulai ex hanya untuk menjalankan suatu :!expandproses itu konyol ...
Martin Tournoij
... dan semua solusi Anda akan mengalahkan file-file biner dan sejenisnya (seperti file .png, file .pdf, dll.)
Martin Tournoij
Ini sejujurnya merupakan saran yang mengerikan untuk dokumentasi - seseorang harus akrab dengan sejumlah sintaks yang agak buram dan masalah semantik dari beberapa program untuk dapat memahami hal ini.
Josip Rodin