Comment puis-je convertir des tabulations en espaces dans chaque fichier d'un répertoire?

251

Comment puis-je convertir des tabulations en espaces dans chaque fichier d'un répertoire (éventuellement récursivement)?

Existe-t-il également un moyen de définir le nombre d'espaces par onglet?

cnd
la source
Vous souhaitez remplacer des onglets dans des fichiers ou des noms de fichiers?
cppcoder
3
prest un merveilleux utilitaire pour cela. Voir cette réponse .
codeforester

Réponses:

69

Avertissement: cela cassera votre repo.

Ce sera des fichiers binaires corrompus , y compris ceux sous svn, .git! Lisez les commentaires avant d'utiliser!

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

Le fichier d'origine est enregistré sous [filename].orig.

Remplacez '* .java' par la fin de fichier du type de fichier que vous recherchez. De cette façon, vous pouvez empêcher la corruption accidentelle des fichiers binaires.

Inconvénients:

  • Remplacera les onglets partout dans un fichier.
  • Cela prendra du temps si vous avez un vidage SQL de 5 Go dans ce répertoire.
Martin Beckett
la source
12
pour l'espace visuel qui est un mélange d'onglets et d'espaces, cette approche donne une expansion incorrecte.
pizza
7
J'ajouterais également un filtreur de fichiers comme par exemple pour les fichiers .php uniquement ./ -iname "* .php" -type f -exec sed -i 's / \ t / / g' {} \;
Daniel Luca CleanUnicorn
98
N'UTILISEZ PAS SED! S'il y a un onglet intégré dans une chaîne, vous pouvez finir par modifier votre code. C'est ce que la commande expand était censée gérer. Utilisez expand.
David W.
5
@DavidW. Je voudrais simplement mettre à jour cette commande pour ne remplacer les onglets qu'à partir du début de la ligne. find ./ -type f -exec sed -i 's/^\t/####/g' {} \;. Mais je n'étais pas au courant de la commande expand - très utile!
Martin Konecny
29
NE PAS UTILISER! Cette réponse vient également de détruire mon dépôt git local. Si vous avez des fichiers contenant des tabulations et des espaces mixtes, il insérera des séquences de #. Utilisez plutôt la réponse de Gene ou le commentaire de Doge ci-dessous.
marionnette
344

Le remplacement simple avec sedest correct mais n'est pas la meilleure solution possible. S'il y a des espaces "supplémentaires" entre les onglets, ils seront toujours là après la substitution, donc les marges seront irrégulières. Les onglets développés au milieu des lignes ne fonctionneront pas non plus correctement. Dans bash, on peut dire à la place

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

à appliquer expandà chaque fichier Java dans l'arborescence de répertoires actuelle. Supprimez / remplacez l' -nameargument si vous ciblez d'autres types de fichiers. Comme l'un des commentaires le mentionne, soyez très prudent lorsque vous supprimez -nameou utilisez un caractère générique faible. Vous pouvez facilement assommer le référentiel et d'autres fichiers cachés sans intention. C'est pourquoi la réponse originale incluait ceci:

Vous devez toujours faire une copie de sauvegarde de l'arborescence avant d'essayer quelque chose comme ça au cas où quelque chose se passe mal.

Gène
la source
2
@JeffreyMartinez Grande question. gniourf_gniourf a modifié ma réponse originale le 11 novembre et a fait des remarques désobligeantes sur le fait de ne pas savoir comment utiliser correctement {}. On dirait qu'il ne savait pas $0quand il -cest utilisé. Ensuite, dimo414 est passé de mon utilisation d'un temp dans le répertoire de conversion à /tmp, ce qui sera beaucoup plus lent s'il se /tmptrouve sur un point de montage différent. Malheureusement, je n'ai pas de boîte Linux disponible pour tester votre $0proposition. Mais je pense que vous avez raison.
Gene
1
@Gene, merci pour la clarification, qui sonne bien comme stackoverflow: p. Pendant que j'y suis, j'ajouterai que j'ai dû utiliser des guillemets autour de '* .java' pour échapper correctement le * .java.
Jeffrey Martinez
2
Si quelqu'un a une erreur "inconnue primaire ou opérateur" de find, alors voici la commande complète qui le corrigera:find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Doge
4
Je pensais que cette réponse n'avait pas suffisamment de commentaires, alors c'est la mienne: si vous l'utilisez spongeavec joeyh.name/code/moreutils , vous pouvez écrirefind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
tokland
8
Ne sois pas stupide et utilise find . -name '*', je viens de détruire mon dépôt git local
Gautam
193

Essayez l'outil de ligne de commande expand.

expand -i -t 4 input | sponge output

  • -i est utilisé pour développer uniquement les onglets de tête sur chaque ligne;
  • -t 4 signifie que chaque onglet sera converti en 4 caractères d'espaces (8 par défaut).
  • spongeprovient du moreutilspackage et évite d' effacer le fichier d'entrée .

Enfin, vous pouvez utiliser gexpandsur OSX, après l'installation coreutilsavec Homebrew ( brew install coreutils).

kev
la source
5
C'est l'un des GNU_Core_Utilities
kev
32
Vous devez passer -ià expandpour remplacer uniquement les tabulations de début sur chaque ligne. Cela permet d'éviter de remplacer des onglets qui pourraient faire partie du code.
Questions Quolonel du
10
que diriez-vous pour chaque fichier dans un répertoire récursivement?
ahnbizcad
4
Chaque fois que j'essaie d'utiliser cela, il supprime certains (généralement tous) des fichiers. : \
ThorSummoner
5
@ThorSummoner: si inputest le même fichier que outputle bash, il encombre le contenu avant même de commencer expand. Voilà comment ça >marche.
Robert Siemer
34

La collecte des meilleurs commentaires de la réponse de Gene , la meilleure solution de loin, consiste à utiliser spongede moreutils .

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

Explication:

  • ./ recherche récursivement à partir du répertoire courant
  • -inameest une correspondance insensible à la casse (pour les deux *.javaet les *.JAVAlikes)
  • type -f ne trouve que des fichiers normaux (pas de répertoires, binaires ou liens symboliques)
  • -exec bash -c exécuter les commandes suivantes dans un sous-shell pour chaque nom de fichier, {}
  • expand -t 4 étend tous les TAB à 4 espaces
  • spongeabsorber l'entrée standard (de expand) et écrire dans un fichier (le même) *.

REMARQUE : * Une simple redirection de fichier ( > "$0") ne fonctionnera pas ici car elle écraserait le fichier trop tôt .

Avantage : toutes les autorisations de fichiers d'origine sont conservées et aucun tmpfichier intermédiaire n'est utilisé.

not2qubit
la source
2
TIL: la merveilleuse commande éponge, après 15 ans d'utilisation de Linux. Merci mystérieux chevalier sur Internet.
sscarduzio
19

Utilisez une barre oblique inversée sed.

Sous Linux:

  • Remplacez tous les onglets par 1 tiret en place, dans tous les fichiers * .txt:

    sed -i $'s/\t/-/g' *.txt
  • Remplacez tous les onglets par 1 espace en place, dans tous les fichiers * .txt:

    sed -i $'s/\t/ /g' *.txt
  • Remplacez tous les onglets par 4 espaces en place, dans tous les fichiers * .txt:

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

Sur un mac:

  • Remplacez tous les onglets par 4 espaces en place, dans tous les fichiers * .txt:

    sed -i '' $'s/\t/    /g' *.txt
e9t
la source
2
@ Машаsed -i '' $'s/\t/ /g' $(find . -name "*.txt")
xyzale
Cette réponse semble être la plus simple.
Yan King Yin
6

Vous pouvez utiliser la prcommande généralement disponible (page de manuel ici ). Par exemple, pour convertir des tabulations en quatre espaces, procédez comme suit:

pr -t -e=4 file > file.expanded
  • -t supprime les en-têtes
  • -e=numélargit les tabulations en numespaces

Pour convertir tous les fichiers d'une arborescence de répertoires de manière récursive, tout en ignorant les fichiers binaires:

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

La logique pour ignorer les fichiers binaires provient de ce post .

REMARQUE:

  1. Cela pourrait être dangereux dans un dépôt git ou svn
  2. Ce n'est pas la bonne solution si vous avez des fichiers de code qui ont des onglets intégrés dans des littéraux de chaîne
codeforester
la source
1
Un avantage sur les expanddeux étant POSIX? Par exemple, a-t-il une option de changement en ligne? Sécurité Git sur: stackoverflow.com/a/52136507/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

Comment puis-je convertir des tabulations en espaces dans chaque fichier d'un répertoire (éventuellement récursivement)?

Ce n'est généralement pas ce que vous voulez.

Voulez-vous le faire pour les images png? Fichiers PDF? Le répertoire .git? Votre Makefile(qui nécessite des onglets)? Un vidage SQL de 5 Go?

Vous pourriez, en théorie, passer un grand nombre d'options d'exclusion vers findou tout ce que vous utilisez; mais cela est fragile et se cassera dès que vous ajouterez d'autres fichiers binaires.

Ce que vous voulez, c'est au moins:

  1. Ignorez les fichiers d'une certaine taille.
  2. Détectez si un fichier est binaire en vérifiant la présence d'un octet NULL.
  3. Ne remplacez les onglets qu'au début d'un fichier ( expandfait cela, sed pas).

Pour autant que je sache, il n'y a pas d'utilitaire Unix "standard" qui puisse faire cela, et ce n'est pas très facile à faire avec un shell one-liner, donc un script est nécessaire.

Il y a quelque temps, j'ai créé un petit script appelé sanitize_files qui fait exactement cela. Il corrige également quelques autres trucs communs comme le remplacement \r\npar \n, l'ajout d'une fin\n , etc.

Vous pouvez trouver un script simplifié sans les fonctionnalités supplémentaires et les arguments de ligne de commande ci-dessous, mais je vous recommande d'utiliser le script ci-dessus car il est plus susceptible de recevoir des corrections de bugs et d'autres mises à jour que ce post.

Je voudrais également souligner, en réponse à certaines des autres réponses ici, que l'utilisation de la globalisation du shell n'est pas un moyen robuste de le faire, car tôt ou tard, vous vous retrouverez avec plus de fichiers que ce qui peut en contenir ARG_MAX(sur les modernes Les systèmes Linux, c'est 128k, ce qui peut sembler beaucoup, mais tôt ou tard ce n'est pas suffisant).


#!/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
la source
Dans git, la vérification binaire est facile: stackoverflow.com/a/52136507/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

J'aime l'exemple "trouver" ci-dessus pour l'application récursive. Pour l'adapter pour qu'il soit non récursif, ne modifiant que les fichiers du répertoire en cours qui correspondent à un caractère générique, l'expansion du shell glob peut être suffisante pour de petites quantités de fichiers:

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

Si vous voulez qu'il soit silencieux après avoir vérifié qu'il fonctionne, déposez simplement -vla shcommande à la fin.

Bien sûr, vous pouvez choisir n'importe quel ensemble de fichiers dans la première commande. Par exemple, répertoriez uniquement un sous-répertoire particulier (ou des répertoires) de manière contrôlée comme ceci:

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

Ou, à son tour, exécutez find (1) avec une combinaison de paramètres de profondeur, etc.:

find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
drchuck
la source
1
Le globbing du shell se cassera tôt ou tard, car la quantité totale de noms de fichiers ne peut être que de ARG_MAXlongueur. Il s'agit de 128k sur les systèmes Linux, mais j'ai rencontré cette limite suffisamment de fois pour ne pas compter sur la globalisation du shell.
Martin Tournoij
1
Vous n'avez pas vraiment besoin de les adapter. findpeut être dit -maxdepth 1, et il ne traite que les entrées du répertoire en cours de modification, pas l'arborescence entière.
ShadowRanger
4

J'avais l'habitude astylede ré-indenter tout mon code C / C ++ après avoir trouvé des tabulations et des espaces mixtes. Il a également des options pour forcer un style d'accolade particulier si vous le souhaitez.

Theo Belaire
la source
4

On peut utiliser vimpour cela:

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

Comme l'a déclaré Carpetsmoker, il sera retab en fonction de vos vimparamètres. Et les modelines dans les fichiers, le cas échéant. De plus, il remplacera les tabulations non seulement au début des lignes. Ce n'est pas ce que vous voulez généralement. Par exemple, vous pourriez avoir des littéraux contenant des tabulations.

x-yuri
la source
:retabchangera tous les onglets d'un fichier, pas ceux du début. cela dépend aussi de ce que sont vos paramètres :tabstopet :expandtabdans le vimrc ou la modeline, donc cela peut ne pas fonctionner du tout.
Martin Tournoij
@Carpetsmoker Bon point sur les onglets au début des lignes. Est-ce que l'une des solutions ici gère ce cas? En ce qui concerne les paramètres tabstopet expandtab, cela fonctionnera si vous utilisez vim. Sauf si vous avez des lignes de mode dans les fichiers.
x-yuri
@ x-yuri bonne question, mais généralement théorique. La plupart des gens n'utilisent pas des onglets réels dans les littéraux.
Ricardo Cruz
4

Ma recommandation est d'utiliser:

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

Commentaires:

  1. Utilisez l'édition sur place. Conservez les sauvegardes dans un VCS. Pas besoin de produire des fichiers * .orig. Il est recommandé de comparer le résultat à votre dernier commit pour vous assurer que cela fonctionne comme prévu, dans tous les cas.
  2. sedest un éditeur de flux. Utiliser expour l'édition sur place. Cela évite de créer des fichiers temporaires supplémentaires et des coquilles d'apparition pour chaque remplacement, comme dans la première réponse .
  3. AVERTISSEMENT: cela dérange tous les onglets, pas seulement ceux utilisés pour l'indentation. De plus, il ne remplace pas les onglets en fonction du contexte. C'était suffisant pour mon cas d'utilisation. Mais cela pourrait ne pas être acceptable pour vous.
  4. EDIT: Une version antérieure de cette réponse a été utilisée à la find|xargsplace de find -exec. Comme indiqué par @ gniourf-gniourf, cela entraîne des problèmes avec les espaces, les guillemets et les caractères de contrôle dans les noms de fichiers cf. Wheeler .
Heinrich Hartmann
la source
expeut ne pas être disponible sur tous les systèmes Unix. Le remplacer par vi -epeut fonctionner sur plus de machines. De plus, votre expression régulière remplace n'importe quel nombre de caractères de tabulation de départ par deux espaces. Remplacez l'expression régulière avec +%s/\t/ /gpour ne pas détruire l'indentation à plusieurs niveaux. Cependant, cela affecte également les caractères de tabulation qui ne sont pas utilisés pour le retrait.
Lukas Schmelzeisen
ex fait partie de POSIX [1] et devrait donc être disponible. Bon point sur l'indentation à plusieurs niveaux. J'avais en fait utilisé la /\t/ /variante sur mes fichiers, mais j'ai opté pour /\t\+//ne pas casser les onglets sans retrait. Vous avez manqué les problèmes de multi-indentation! Mise à jour de la réponse. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSO
Heinrich Hartmann
2
L'utilisation xargsde cette manière est inutile, inefficace et cassée (pensez aux noms de fichiers contenant des espaces ou des guillemets). Pourquoi n'utilisez-vous pas findle -execcommutateur de?
gniourf_gniourf
Je dirais que les noms de fichiers avec des espaces et des guillemets sont brisés; ) Si vous avez besoin de prendre en charge, je choisirais: -print0options pour trouver / xargs. J'aime les xargs -execcar: a) Séparation des préoccupations b) il peut être échangé avec GNU parallèle plus facilement.
Heinrich Hartmann
Mise à jour en ajoutant des commentaires @gniourf_gniourf.
Heinrich Hartmann
4

Pour convertir récursivement tous les fichiers Java dans un répertoire pour utiliser 4 espaces au lieu d'un onglet:

find . -type f -name *.java -exec bash -c 'expand -t 4 {} > /tmp/stuff;mv /tmp/stuff {}' \;
Raffi Khatchadourian
la source
En quoi cette réponse est-elle différente de celle qui a été publiée il y a 4 ans?
PP
2
Votre réponse aussi. En fait, ceci est une version inférieure de la réponse de Gene: 1) La réponse de Gene prend en charge les répertoires du même nom. 2) Il ne bouge pas si l'extension échoue.
PP
4

Vous pouvez utiliser findavectabs-to-spaces package pour cela.

Tout d'abord, installez tabs-to-spaces

npm install -g tabs-to-spaces

ensuite, exécutez cette commande à partir du répertoire racine de votre projet;

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

Cela remplacera chaque tabcaractère par 2 spacesdans chaque fichier.

Harsh Vakharia
la source
3

Aucun organisme mentionné rpl? En utilisant rpl, vous pouvez remplacer n'importe quelle chaîne. Pour convertir des tabulations en espaces,

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

très simple.

PeopleMoutainPeopleSea
la source
1
Cela a corrompu tous les fichiers binaires de mon dépôt.
Aaron Franke
1
Une excellente commande, mais potentiellement dangereuse avec l'option récursive et tous les fichiers dans le dossier comme spécifié ci-dessus. J'ajouterais l'option --dry-run "juste au cas où" pour m'assurer que vous êtes assis dans le bon dossier.
MortimerCat
2

L'utilisation de expandcomme suggéré dans d'autres réponses semble l'approche la plus logique pour cette seule tâche.

Cela dit, cela peut également être fait avec Bash et Awk au cas où vous souhaiteriez apporter d'autres modifications en même temps.

Si vous utilisez Bash 4.0 ou une version supérieure, la fonction intégrée shopt globstar peut être utilisée pour effectuer une recherche récursive avec **.

Avec GNU Awk version 4.1 ou supérieure, des modifications de fichiers sed comme "inplace" peuvent être effectuées:

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

Si vous souhaitez définir le nombre d'espaces par tabulation:

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

Téléchargez et exécutez le script suivant pour convertir récursivement les onglets matériels en onglets logiciels dans des fichiers en texte brut.

Exécutez le script à l'intérieur du dossier qui contient les fichiers de texte brut.

#!/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
la source
2

Méthode conviviale pour le référentiel 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"
)

Agissez sur tous les fichiers du répertoire courant:

git-tab-to-space

Agir uniquement sur les fichiers C ou C ++:

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

Vous le voulez probablement, notamment à cause de ces Makefiles ennuyeux qui nécessitent des onglets.

La commande git grep --cached -Il '':

  • répertorie uniquement les fichiers suivis, donc rien à l'intérieur .git
  • exclut les répertoires, les fichiers binaires (seraient corrompus) et les liens symboliques (seraient convertis en fichiers normaux)

comme expliqué à: Comment lister tous les fichiers texte (non binaires) dans un dépôt git?

chmod --referenceconserve les autorisations de fichier inchangées: /unix/20645/clone-ownership-and-permissions-from-another-file Malheureusement, je ne trouve pas d'alternative POSIX succincte .

Si votre base de code a eu l'idée folle d'autoriser les onglets bruts fonctionnels dans les chaînes, utilisez:

expand -i

puis amusez-vous à parcourir tous les onglets non en début de ligne un par un, que vous pouvez lister avec: Est-il possible de git grep pour les onglets?

Testé sur Ubuntu 18.04.

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

Conversion des tabulations en espace en seulement dans des fichiers ".lua" [tabulations -> 2 espaces]

find . -iname "*.lua" -exec sed -i "s#\t#  #g" '{}' \;
Makah
la source
De toute évidence, la quantité d'espace à laquelle un onglet s'étend dépend du contexte. Ainsi, sed est un outil totalement inapproprié pour la tâche.
Sven
?? @Sven, ma commande sed fait la même chose que la commande expand ( expand -t 4 input >output)
Makah
3
Bien sûr que non. expand -t 4étendra l'onglet a\tbà 3 espaces et l'onglet aa\tbà 2 espaces, comme il se doit. expandprend en compte le contexte d'un onglet, sedne le remplace pas et le remplacera par le nombre d'espaces que vous spécifiez, quel que soit le contexte.
Sven
-1

Utilisez le vim-way:

$ ex +'bufdo retab' -cxa **/*.*
  • Faites la sauvegarde! avant d'exécuter la commande ci-dessus, car cela peut corrompre vos fichiers binaires.
  • Pour utiliser globstar( **) pour la récursivité, activez par shopt -s globstar.
  • Pour spécifier le type de fichier spécifique, utilisez par exemple: **/*.c.

Pour modifier la tabulation, ajoutez +'set ts=2'.

Cependant, l'inconvénient est qu'il peut remplacer les onglets à l'intérieur des chaînes .

Donc, pour une solution légèrement meilleure (en utilisant la substitution), essayez:

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

Ou en utilisant exéditeur + expandutilitaire:

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

Pour les espaces de fin, voir: Comment supprimer les espaces de fin pour plusieurs fichiers?


Vous pouvez ajouter la fonction suivante dans votre .bash_profile:

# Convert tabs to spaces.
# Usage: retab *.*
# See: https://stackoverflow.com/q/11094383/55075
retab() {
  ex +'set ts=2' +'bufdo retab' -cxa $*
}
Kenorb
la source
J'ai downvoté de nombreuses réponses dans ce fil, pas seulement la vôtre ;-) Les raisons sont: :retab peut ne pas fonctionner du tout , le globglement de shell est une mauvaise solution pour ce genre de chose , votre :scommande remplacera toute quantité d'onglets avec 2 espaces (que vous avez presque ne veut jamais), commencer ex juste pour exécuter un :!expandprocessus est idiot ...
Martin Tournoij
... et toutes vos solutions encombreront les fichiers binaires et autres (comme les fichiers .png, les fichiers .pdf, etc.)
Martin Tournoij
C'est franchement une suggestion horrible pour la documentation - il faut être intimement familiarisé avec un certain nombre de syntaxe assez opaque et les problèmes sémantiques de plusieurs programmes pour pouvoir comprendre cela.
Josip Rodin