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.
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
à 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.
@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
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 .
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:
Cela pourrait être dangereux dans un dépôt git ou svn
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
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:
Ignorez les fichiers d'une certaine taille.
Détectez si un fichier est binaire en vérifiant la présence d'un octet NULL.
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:returnTruereturnFalse
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))continueif size ==0:continueif 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))continueif is_binary(data):
print("Skipping `%s' because it looks binary"% f)continue
data = data.split(b'\n')
fixed_indent =Falsefor i, line in enumerate(data):# Fix indentation
repl_count =0while 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)
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.:
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.
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.
: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:
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.
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 .
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.
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 .
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:
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.
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 shoptglobstar 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:
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.
... 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.
pr
est un merveilleux utilitaire pour cela. Voir cette réponse .Réponses:
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:
la source
expand
.find ./ -type f -exec sed -i 's/^\t/####/g' {} \;
. Mais je n'étais pas au courant de la commande expand - très utile!Le remplacement simple avec
sed
est 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. Dansbash
, on peut dire à la placeà appliquer
expand
à chaque fichier Java dans l'arborescence de répertoires actuelle. Supprimez / remplacez l'-name
argument si vous ciblez d'autres types de fichiers. Comme l'un des commentaires le mentionne, soyez très prudent lorsque vous supprimez-name
ou 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:la source
{}
. On dirait qu'il ne savait pas$0
quand il-c
est 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/tmp
trouve sur un point de montage différent. Malheureusement, je n'ai pas de boîte Linux disponible pour tester votre$0
proposition. Mais je pense que vous avez raison.find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
sponge
avec joeyh.name/code/moreutils , vous pouvez écrirefind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
find . -name '*'
, je viens de détruire mon dépôt git localEssayez l'outil de ligne de commande
expand
.où
-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).sponge
provient dumoreutils
package et évite d' effacer le fichier d'entrée .Enfin, vous pouvez utiliser
gexpand
sur OSX, après l'installationcoreutils
avec Homebrew (brew install coreutils
).la source
-i
àexpand
pour remplacer uniquement les tabulations de début sur chaque ligne. Cela permet d'éviter de remplacer des onglets qui pourraient faire partie du code.input
est le même fichier queoutput
le bash, il encombre le contenu avant même de commencerexpand
. Voilà comment ça>
marche.La collecte des meilleurs commentaires de la réponse de Gene , la meilleure solution de loin, consiste à utiliser
sponge
de moreutils .Explication:
./
recherche récursivement à partir du répertoire courant-iname
est une correspondance insensible à la casse (pour les deux*.java
et les*.JAVA
likes)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 espacessponge
absorber l'entrée standard (deexpand
) 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
tmp
fichier intermédiaire n'est utilisé.la source
Utilisez une barre oblique inversée
sed
.Sous Linux:
Remplacez tous les onglets par 1 tiret en place, dans tous les fichiers * .txt:
Remplacez tous les onglets par 1 espace en place, dans tous les fichiers * .txt:
Remplacez tous les onglets par 4 espaces en place, dans tous les fichiers * .txt:
Sur un mac:
Remplacez tous les onglets par 4 espaces en place, dans tous les fichiers * .txt:
la source
sed -i '' $'s/\t/ /g' $(find . -name "*.txt")
Vous pouvez utiliser la
pr
commande généralement disponible (page de manuel ici ). Par exemple, pour convertir des tabulations en quatre espaces, procédez comme suit:-t
supprime les en-têtes-e=num
élargit les tabulations ennum
espacesPour convertir tous les fichiers d'une arborescence de répertoires de manière récursive, tout en ignorant les fichiers binaires:
La logique pour ignorer les fichiers binaires provient de ce post .
REMARQUE:
la source
expand
deux étant POSIX? Par exemple, a-t-il une option de changement en ligne? Sécurité Git sur: stackoverflow.com/a/52136507/895245Ce 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
find
ou 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:
expand
fait 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\n
par\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).la source
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:
Si vous voulez qu'il soit silencieux après avoir vérifié qu'il fonctionne, déposez simplement
-v
lash
commande à 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:
Ou, à son tour, exécutez find (1) avec une combinaison de paramètres de profondeur, etc.:
la source
ARG_MAX
longueur. 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.find
peut être dit-maxdepth 1
, et il ne traite que les entrées du répertoire en cours de modification, pas l'arborescence entière.J'avais l'habitude
astyle
de 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.la source
On peut utiliser
vim
pour cela:Comme l'a déclaré Carpetsmoker, il sera retab en fonction de vos
vim
paramè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.la source
:retab
changera tous les onglets d'un fichier, pas ceux du début. cela dépend aussi de ce que sont vos paramètres:tabstop
et:expandtab
dans le vimrc ou la modeline, donc cela peut ne pas fonctionner du tout.tabstop
etexpandtab
, cela fonctionnera si vous utilisezvim
. Sauf si vous avez des lignes de mode dans les fichiers.Ma recommandation est d'utiliser:
Commentaires:
sed
est un éditeur de flux. Utiliserex
pour 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 .find|xargs
place defind -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 .la source
ex
peut ne pas être disponible sur tous les systèmes Unix. Le remplacer parvi -e
peut 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/ /g
pour 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./\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%A0ALSOxargs
de cette manière est inutile, inefficace et cassée (pensez aux noms de fichiers contenant des espaces ou des guillemets). Pourquoi n'utilisez-vous pasfind
le-exec
commutateur de?-print0
options pour trouver / xargs. J'aime les xargs-exec
car: a) Séparation des préoccupations b) il peut être échangé avec GNU parallèle plus facilement.Pour convertir récursivement tous les fichiers Java dans un répertoire pour utiliser 4 espaces au lieu d'un onglet:
la source
Vous pouvez utiliser
find
avectabs-to-spaces
package pour cela.Tout d'abord, installez
tabs-to-spaces
ensuite, exécutez cette commande à partir du répertoire racine de votre projet;
Cela remplacera chaque
tab
caractère par 2spaces
dans chaque fichier.la source
Aucun organisme mentionné
rpl
? En utilisant rpl, vous pouvez remplacer n'importe quelle chaîne. Pour convertir des tabulations en espaces,très simple.
la source
L'utilisation de
expand
comme 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:
Si vous souhaitez définir le nombre d'espaces par tabulation:
la source
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.
la source
Méthode conviviale pour le référentiel Git
Agissez sur tous les fichiers du répertoire courant:
Agir uniquement sur les fichiers C ou C ++:
Vous le voulez probablement, notamment à cause de ces Makefiles ennuyeux qui nécessitent des onglets.
La commande
git grep --cached -Il ''
:.git
comme expliqué à: Comment lister tous les fichiers texte (non binaires) dans un dépôt git?
chmod --reference
conserve 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:
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.
la source
Conversion des tabulations en espace en seulement dans des fichiers ".lua" [tabulations -> 2 espaces]
la source
expand -t 4 input >output
)expand -t 4
étendra l'ongleta\tb
à 3 espaces et l'ongletaa\tb
à 2 espaces, comme il se doit.expand
prend en compte le contexte d'un onglet,sed
ne le remplace pas et le remplacera par le nombre d'espaces que vous spécifiez, quel que soit le contexte.Utilisez le vim-way:
globstar
(**
) pour la récursivité, activez parshopt -s globstar
.**/*.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:
Ou en utilisant
ex
éditeur +expand
utilitaire: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
:la source
:retab
peut ne pas fonctionner du tout , le globglement de shell est une mauvaise solution pour ce genre de chose , votre:s
commande remplacera toute quantité d'onglets avec 2 espaces (que vous avez presque ne veut jamais), commencer ex juste pour exécuter un:!expand
processus est idiot ...