Jak przekonwertować tabulatory na spacje w każdym pliku katalogu?


251

Jak przekonwertować tabulatory na spacje w każdym pliku katalogu (ewentualnie rekurencyjnie)?

Czy istnieje również sposób ustawienia liczby spacji na zakładkę?


Chcesz zastąpić tabulatory w plikach lub nazwach plików?
cppcoder,

3
prto wspaniałe narzędzie do tego. Zobacz tę odpowiedź .
codeforester,

Odpowiedzi:


69

Ostrzeżenie: spowoduje to uszkodzenie Twojego repozytorium.

This will uszkodzone pliki binarne , w tym osób poniżej svn, .git! Przeczytaj komentarze przed użyciem!

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

Oryginalny plik zostanie zapisany jako [filename].orig.

Zamień „* .java” na końcówkę pliku, którego szukasz. W ten sposób można zapobiec przypadkowemu uszkodzeniu plików binarnych.

Wady:

  • Zamieni tabulatory wszędzie w pliku.
  • Zajmie to dużo czasu, jeśli zdarzy ci się mieć zrzut pamięci SQL o pojemności 5 GB w tym katalogu.

12
w przypadku przestrzeni wizualnej, która jest kombinacją tabulatorów i spacji, to podejście daje niepoprawne rozwinięcie.
pizza

7
Dodałbym także dopasowywanie plików, takie jak na przykład tylko dla plików .php find ./ -iname "* .php" -type f -exec sed -i 's / \ t / / g' {} \;
Daniel Luca CleanUnicorn

98
NIE UŻYWAJ SED! Jeśli w ciągu znajduje się osadzona karta, może to skończyć się błędnym kodowaniem. To właśnie miało obsługiwać polecenie rozwijania . Zastosowanie expand.
David W.

5
@DavidW. Chciałbym po prostu zaktualizować to polecenie, aby zastąpić tabulatory tylko od początku wiersza. find ./ -type f -exec sed -i 's/^\t/####/g' {} \;. Ale nie wiedziałem o poleceniu rozwijania - bardzo przydatne!
Martin Konecny

29
NIE UŻYWAĆ! Ta odpowiedź właśnie zniszczyła moje lokalne repozytorium git. Jeśli masz pliki zawierające mieszane tabulatory i spacje, wstawi sekwencje #. Zamiast tego użyj odpowiedzi Gene'a lub komentarza Doge poniżej.
marionetka

344

Prosta wymiana sedjest w porządku, ale nie jest najlepszym możliwym rozwiązaniem. Jeśli między zakładkami znajdują się „dodatkowe” spacje, nadal będą one występować po zamianie, więc marginesy będą nierówne. Karty rozszerzone w środku linii również nie będą działać poprawnie. W bash, możemy powiedzieć, zamiast

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

do zastosowania expanddo każdego pliku Java w bieżącym drzewie katalogów. Usuń / zamień -nameargument, jeśli celujesz na inne typy plików. Jak wspomina jeden z komentarzy, zachowaj ostrożność podczas usuwania -namelub używania słabej, wieloznacznej karty. Możesz z łatwością zamykać repozytorium i inne ukryte pliki bez intencji. Oto dlaczego pierwotna odpowiedź zawierała to:

Zawsze powinieneś wykonać kopię zapasową drzewa przed wypróbowaniem czegoś takiego na wypadek, gdyby coś poszło nie tak.


2
@JeffreyMartinez Świetne pytanie. gniourf_gniourf zredagował moją oryginalną odpowiedź 11 listopada i wypowiedział obraźliwe uwagi na temat braku znajomości właściwego sposobu korzystania {}. Wygląda na to, że nie wiedział, $0kiedy -cjest używany. Następnie dimo414 zmienił się z mojego użycia temp w katalogu konwersji na /tmp, który będzie znacznie wolniejszy, jeśli /tmpbędzie w innym punkcie montowania. Niestety nie mam dostępnego Linux-a do przetestowania twojej $0propozycji. Ale myślę, że masz rację.
Gene,

1
@Gene, dzięki za wyjaśnienie, które brzmi jak stackoverflow w porządku: p. Chociaż jestem przy tym, dodam, że musiałem używać cudzysłowów wokół „* .java”, aby właściwie uciec z * .java.
Jeffrey Martinez

2
Jeśli ktoś ma błąd „nieznany główny lub operator” podczas wyszukiwania, oto pełne polecenie, które to naprawi:find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Doży

4
Pomyślałem, że ta odpowiedź nie ma wystarczająco dużo komentarzy, więc jest moja: jeśli skorzystasz spongez joeyh.name/code/moreutils , możesz napisaćfind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
tokland

8
Nie bądź głupi i używaj find . -name '*', właśnie zniszczyłem moje lokalne repozytorium git
Gautam

193

Wypróbuj narzędzie wiersza polecenia expand.

expand -i -t 4 input | sponge output

gdzie

  • -i służy do rozwijania tylko wiodących kart w każdej linii;
  • -t 4 oznacza, że ​​każda karta zostanie przekonwertowana na 4 znaki białych znaków (domyślnie 8).
  • spongepochodzi z moreutilspakietu i pozwala uniknąć czyszczenia pliku wejściowego .

Wreszcie możesz korzystać gexpandz systemu OSX po instalacji za coreutilspomocą Homebrew ( brew install coreutils).


5
Jest to jeden z GNU_Core_Utilities
kev

32
Powinieneś przejść -ido, expandaby zastąpić tylko wiodące tabulatory w każdej linii. Pomaga to uniknąć zamiany kart, które mogą być częścią kodu.
Pytania do kolonistów

10
co powiesz na każdy rekursywnie każdy plik w katalogu?
ahnbizcad

4
Za każdym razem, gdy próbuję tego użyć, usuwa niektóre (zwykle wszystkie) pliki. : \
ThorSummoner

5
@ThorSummoner: if inputjest tym samym plikiem, co outputbash blokuje zawartość, zanim jeszcze się uruchomi expand. Tak to >działa.
Robert Siemer,

34

Zbieranie najlepszych komentarzy z odpowiedzi Gene'a , najlepszym jak dotąd najlepszym rozwiązaniem jest korzystanie spongez moreutils .

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

Wyjaśnienie:

  • ./ rekurencyjnie szuka z bieżącego katalogu
  • -inamejest dopasowanie bez rozróżniania wielkości liter (dla obu *.javai *.JAVApolubień)
  • type -f znajduje tylko zwykłe pliki (bez katalogów, plików binarnych lub dowiązań symbolicznych)
  • -exec bash -c wykonaj następujące polecenia w podpowłoce dla każdej nazwy pliku, {}
  • expand -t 4 rozszerza wszystkie tabele do 4 pól
  • spongewchłonąć standardowe wejście (z expand) i zapisać do pliku (tego samego) *.

UWAGA : * Proste przekierowanie pliku ( > "$0") nie będzie tutaj działać, ponieważ zbyt wcześnie nadpisze plik .

Zaleta : wszystkie oryginalne uprawnienia do plików są zachowane i nie tmpsą używane żadne pliki pośrednie .


2
TIL: cudowne polecenie gąbki, po 15 latach używania Linuksa. Dziękuję tajemniczy rycerzu z Internetu.
sscarduzio,

19

Użyj znaku odwrotnego ukośnika sed.

W systemie Linux:

  • Zamień wszystkie karty na 1 łącznik na miejscu we wszystkich plikach * .txt:

    sed -i $'s/\t/-/g' *.txt
  • Zamień wszystkie karty na 1 miejsce w miejscu, we wszystkich plikach * .txt:

    sed -i $'s/\t/ /g' *.txt
  • Zamień wszystkie tabulatory na 4 spacje we wszystkich plikach * .txt:

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

Na komputerze Mac:

  • Zamień wszystkie tabulatory na 4 spacje we wszystkich plikach * .txt:

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

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

Ta odpowiedź wydaje się najprostsza.
Yan King Yin

6

Możesz użyć ogólnie dostępnego prpolecenia ( tutaj strona podręcznika ). Na przykład, aby przekonwertować tabulatory na cztery spacje, wykonaj następujące czynności:

pr -t -e=4 file > file.expanded
  • -t pomija nagłówki
  • -e=numrozwija tabulatory do numspacji

Aby rekurencyjnie przekonwertować wszystkie pliki w drzewie katalogów, pomijając pliki binarne:

#!/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 pomijania plików binarnych pochodzi z tego postu .

UWAGA:

  1. Może to być niebezpieczne w repozytorium git lub svn
  2. Nie jest to właściwe rozwiązanie, jeśli masz pliki kodu, których tabulatory są osadzone w literałach łańcuchowych

1
Czy jest jakaś przewaga nad expandtym, że oba są POSIX? Np. Czy ma wbudowaną opcję zmiany? Git safety at: stackoverflow.com/a/52136507/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

5

Jak przekonwertować tabulatory na spacje w każdym pliku katalogu (ewentualnie rekurencyjnie)?

Zwykle nie jest to, czego chcesz.

Czy chcesz to zrobić dla obrazów PNG? Pliki PDF? Katalog .git? Twój Makefile(który wymaga zakładek)? Zrzut SQL 5 GB?

Teoretycznie możesz przekazać wiele opcji wykluczania findlub cokolwiek innego, czego używasz; ale jest to kruche i zepsuje się, gdy tylko dodasz inne pliki binarne.

Co chcesz, to co najmniej:

  1. Pomiń pliki o określonym rozmiarze.
  2. Wykryj, czy plik jest binarny, sprawdzając obecność bajtu NULL.
  3. Zastępuj tabulatory tylko na początku pliku ( expandrobi to, sed nie robi).

O ile mi wiadomo, nie ma „standardowego” narzędzia uniksowego, które mogłoby to zrobić i nie jest to bardzo łatwe w przypadku powłoki jednowierszowej, więc potrzebny jest skrypt.

Jakiś czas temu stworzyłem mały skrypt o nazwie sanitize_files, który właśnie to robi. Naprawia również kilka innych rzeczy jak zastąpienie wspólnego \r\nz \ndodanie końcowego znaku \n, itd.

Możesz znaleźć uproszczony skrypt bez dodatkowych funkcji i argumentów wiersza poleceń poniżej, ale zalecamy użycie powyższego skryptu, ponieważ jest bardziej prawdopodobne, że otrzyma poprawki błędów i inne zaktualizowane niż ten post.

Chciałbym również wskazać, w odpowiedzi na niektóre inne odpowiedzi tutaj, że użycie globowania powłoki nie jest solidnym sposobem na zrobienie tego, ponieważ wcześniej czy później skończy się więcej plików, niż zmieści się ARG_MAX(w nowoczesnych Systemy Linux to 128k, co może wydawać się dużo, ale wcześniej czy później to nie wystarczy).


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

Podoba mi się powyższy przykład „znajdź” dla aplikacji rekurencyjnej. Aby dostosować go tak, aby nie był rekurencyjny, zmieniając tylko pliki w bieżącym katalogu, które pasują do znaku wieloznacznego, rozszerzenie globu powłoki może być wystarczające dla małych ilości plików:

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

Jeśli chcesz to cichy po ufasz, że to działa, po prostu upuść -vna shpolecenia na końcu.

Oczywiście możesz wybrać dowolny zestaw plików w pierwszym poleceniu. Na przykład, wypisz tylko określony podkatalog (lub katalogi) w kontrolowany sposób:

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

Lub z kolei uruchom find (1) z pewną kombinacją parametrów głębokości itp .:

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

1
Globowanie powłoki załamie się wcześniej czy później, ponieważ całkowita liczba nazw plików może być tylko ARG_MAXdługa. Jest to 128k w systemach Linux, ale napotkałem ten limit wystarczająco dużo razy, aby nie polegać na globowaniu powłoki.
Martin Tournoij,

1
Naprawdę nie musisz ich dostosowywać. findmożna powiedzieć -maxdepth 1, i przetwarza tylko wpisy modyfikowanego katalogu, a nie całe drzewo.
ShadowRanger

4

Użyłem astyledo re-indent wszyscy moi C / C ++ kod po znalezieniu mieszane kart i spacji. Ma także opcje wymuszenia określonego stylu nawiasów, jeśli chcesz.


4

Można vimdo tego użyć :

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

Jak stwierdził Carpetsmoker, nastąpi zmiana w zależności od twoich vimustawień. I modeliny w plikach, jeśli istnieją. Ponadto zastąpi tabulatory nie tylko na początku linii. Którego na ogół nie chcesz. Na przykład możesz mieć literały zawierające tabulatory.


:retabzmieni wszystkie zakładki w pliku, a nie te na początku. zależy to również od tego, jakie są twoje ustawienia :tabstopi :expandtabustawienia w vimrc lub modeline, więc może to wcale nie działać.
Martin Tournoij,

@Carpetsmoker Dobra uwaga na temat kart na początku linii. Czy którekolwiek z rozwiązań tutaj obsługuje ten przypadek? Jeśli chodzi o ustawienia tabstopi expandtab, zadziała, jeśli używasz vim. Chyba że w plikach znajdują się linie trybu.
x-yuri,

@ x-yuri dobre pytanie, ale generalnie dyskusyjne. Większość ludzi nie używa rzeczywistych zakładek w literałach.
Ricardo Cruz,

4

Polecam użyć:

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

Komentarze:

  1. Użyj edycji na miejscu. Przechowuj kopie zapasowe w VCS. Nie trzeba tworzyć plików * .orig. Dobrą praktyką jest różnicowanie wyniku względem ostatniego zatwierdzenia, aby upewnić się, że zadziałało zgodnie z oczekiwaniami.
  2. sedjest edytorem strumieniowym. Użyj exdo edycji na miejscu. Pozwala to uniknąć tworzenia dodatkowych plików tymczasowych i odradzania powłok dla każdej zamiany, jak w pliku pierwszej odpowiedzi .
  3. OSTRZEŻENIE: Spełnia to wszystkie zakładki, nie tylko te używane do wcięcia. Nie zmienia też kontekstowego zastępowania kart. To wystarczyło w moim przypadku użycia. Ale może być dla ciebie nie do przyjęcia.
  4. EDIT: Wcześniejsza wersja tej odpowiedzi używany find|xargszamiast find -exec. Jak wskazał @ gniourf-gniourf, prowadzi to do problemów ze spacjami, cudzysłowami i znakami kontrolnymi w nazwach plików por. Wheeler .

exmoże nie być dostępny w każdym systemie Unix. Zastąpienie go vi -emoże działać na większej liczbie komputerów. Ponadto wyrażenie regularne zamienia dowolną liczbę początkowych znaków tabulacji na dwie spacje. Zamień wyrażenie regularne na, +%s/\t/ /gaby nie niszczyć wielopoziomowego wcięcia. Wpływa to jednak również na znaki tabulacji, które nie są używane do wcięcia.
Lukas Schmelzeisen

ex jest częścią POSIX [1], więc powinna być dostępna. Dobra uwaga na temat indukcji wielopoziomowej. W rzeczywistości użyłem tego /\t/ /wariantu w moich plikach, ale zdecydowałem /\t\+//się nie łamać tabulatorów bez wcięć. Pominięto problemy z wielokrotnym wcięciem! Aktualizacja odpowiedzi. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSO
Heinrich Hartmann

2
Używanie xargsw ten sposób jest bezużyteczne, nieefektywne i zepsute (pomyśl o nazwach plików zawierających spacje lub cudzysłowy). Dlaczego nie używacie find„s -execprzełącznik zamiast?
gniourf_gniourf

Twierdziłbym, że nazwy plików ze spacjami i cudzysłowami są zepsute; ) Jeśli potrzebujesz wsparcia, które wybrałbym: -print0opcje find / xargs. Lubię xargs -execod kiedy: a) Rozdzielenie obaw b) można łatwiej zamieniać GNU równolegle.
Heinrich Hartmann

Zaktualizowano dodawanie komentarzy @gniourf_gniourf.
Heinrich Hartmann

4

Aby przekonwertować rekurencyjnie wszystkie pliki Java w katalogu, tak aby używały 4 spacji zamiast tabulacji:

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

Czym różni się ta odpowiedź od tej, która została opublikowana 4 lata temu?
PP

2
Twoja odpowiedź też. W rzeczywistości jest to gorsza wersja odpowiedzi Gene'a: ​​1) Odpowiedź Gene'a zajmuje się katalogami o tej samej nazwie. 2) Nie porusza się, jeśli rozszerzenie nie powiedzie się.
PP

4

Można skorzystać findz tabs-to-spacespakietu do tego.

Najpierw zainstaluj tabs-to-spaces

npm install -g tabs-to-spaces

następnie uruchom to polecenie z katalogu głównego swojego projektu;

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

Spowoduje to zastąpienie każdego tabznaku wartością 2 spacesw każdym pliku.


3

Nie wspomniano o ciele rpl? Za pomocą rpl możesz zamienić dowolny ciąg. Aby przekonwertować tabulatory na spacje,

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

bardzo prosty.


1
Spowodowało to uszkodzenie wszystkich plików binarnych w moim repozytorium.
Aaron Franke,

1
Doskonałe polecenie, ale potencjalnie niebezpieczne z opcją rekursywną i wszystkimi plikami w folderze, jak określono powyżej. Dodałbym opcję --dry-run „na wszelki wypadek”, aby upewnić się, że siedzisz we właściwym folderze.
MortimerCat

2

Zastosowanie, expandjak sugerowano w innych odpowiedziach, wydaje się najbardziej logicznym podejściem do samego zadania.

To powiedziawszy, można to również zrobić za pomocą Bash i Awk, na wypadek, gdybyś mógł chcieć wprowadzić inne modyfikacje wraz z nim.

Jeśli używasz Bash 4.0 lub nowszego, wbudowanego shopt globstar można używać do wyszukiwania rekurencyjnego **.

W GNU Awk w wersji 4.1 lub nowszej można wprowadzać modyfikacje plików typu „inplace”:

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

Jeśli chcesz ustawić liczbę spacji na zakładkę:

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

2

Pobierz i uruchom następujący skrypt, aby rekurencyjnie konwertować twarde karty na miękkie karty w zwykłych plikach tekstowych.

Uruchom skrypt z folderu zawierającego zwykłe pliki tekstowe.

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

Metoda przyjazna dla repozytorium Git

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

Działaj na wszystkie pliki w bieżącym katalogu:

git-tab-to-space

Działaj tylko na plikach C lub C ++:

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

Prawdopodobnie chcesz tego, szczególnie z powodu tych irytujących plików Makefile, które wymagają zakładek.

Polecenie git grep --cached -Il '':

  • wyświetla tylko śledzone pliki, więc nic w środku .git
  • nie obejmuje katalogów, plików binarnych (zostanie uszkodzony) i dowiązań symbolicznych (zostanie przekonwertowany na zwykłe pliki)

jak wyjaśniono na: Jak wyświetlić listę wszystkich plików tekstowych (niebinarnych) w repozytorium git?

chmod --referenceuprawnienia do plików pozostają niezmienione: /unix/20645/clone-ownership-and-permissions-from-another-file Niestety nie mogę znaleźć zwięzłej alternatywy POSIX .

Jeśli twoja baza kodu wpadła na szalony pomysł, aby zezwolić na funkcjonalne nieprzetworzone tabulacje w łańcuchach, użyj:

expand -i

a potem baw się dobrze, przeglądając kolejno wszystkie nie uruchamiane karty linii, które możesz wypisać: Czy można używać grep dla kart?

Testowane na Ubuntu 18.04.


-1

Konwersja tabulatorów na spacje w plikach „.lua” [tabs -> 2 spacje]

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

Oczywiście ilość miejsca, na które powiększa się karta, zależy od kontekstu. Sed jest więc całkowicie nieodpowiednim narzędziem do tego zadania.
Sven

?? @ Sev, moja komenda sed robi to samo, co komenda expand ( expand -t 4 input >output)
Makah

3
Oczywiście nie. expand -t 4powiększy tabulator a\tbdo 3 spacji, a tab aa\tbdo 2 spacji, tak jak powinien być. expandbierze pod uwagę kontekst karty, sednie zastępuje i zastępuje określoną przez Ciebie ilością spacji, niezależnie od kontekstu.
Sven

-1

Użyj vim-way:

$ ex +'bufdo retab' -cxa **/*.*
  • Wykonaj kopię zapasową! przed wykonaniem powyższego polecenia, ponieważ może to spowodować uszkodzenie plików binarnych.
  • Aby użyć globstar( **) do rekurencji, aktywuj za pomocą shopt -s globstar.
  • Aby określić konkretny typ pliku, należy użyć np **/*.c.

Aby zmodyfikować tabstop, dodaj +'set ts=2'.

Jednak wadą jest to, że może zastąpić zakładki wewnątrz ciągów .

Aby uzyskać nieco lepsze rozwiązanie (przy użyciu podstawienia), spróbuj:

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

Lub za pomocą exedytora + expandnarzędzie:

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

Aby zobaczyć końcowe spacje, zobacz: Jak usunąć końcowe białe spacje dla wielu plików?


Możesz dodać następującą funkcję do swojego .bash_profile:

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

W tym wątku zanotowałem wiele odpowiedzi, nie tylko twoich ;-) Powody są następujące: :retabmoże w ogóle nie działać , globowanie powłoki jest złym rozwiązaniem dla tego rodzaju rzeczy , twoje :spolecenie zastąpi dowolną liczbę tabulatorów 2 spacjami (które prawie nigdy nie chcę), rozpoczęcie ex po prostu uruchomienia :!expandprocesu jest głupie ...
Martin Tournoij

... a wszystkie twoje rozwiązania będą blokować pliki binarne i takie (jak pliki .png, pliki .pdf itp.)
Martin Tournoij

Jest to szczerze mówiąc okropna sugestia dla dokumentacji - trzeba dokładnie zapoznać się z szeregiem dość nieprzejrzystej składni i problemów semantycznych kilku programów, aby móc to zrozumieć.
Josip Rodin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.