Sie möchten Registerkarten in Dateien oder Dateinamen ersetzen?
Cppcoder
3
prist ein wunderbarer Nutzen dafür. Siehe diese Antwort .
Codeforester
Antworten:
69
Warnung: Dies wird Ihr Repo brechen.
Diese werden korrupte Binärdateien , einschließlich derjenigen unter svn, .git! Lesen Sie die Kommentare vor der Verwendung!
find . -iname '*.java' -type f -exec sed -i.orig 's/\t/ /g' {} +
Die Originaldatei wird als gespeichert [filename].orig.
Ersetzen Sie '* .java' durch das Dateiende des gesuchten Dateityps. Auf diese Weise können Sie eine versehentliche Beschädigung von Binärdateien verhindern.
Nachteile:
Ersetzt Tabs überall in einer Datei.
Dies dauert lange, wenn sich in diesem Verzeichnis ein 5-GB-SQL-Speicherauszug befindet.
Für visuellen Raum, der eine Mischung aus Tabulatoren und Leerzeichen ist, führt dieser Ansatz zu einer falschen Erweiterung.
Pizza
7
Ich würde auch einen Datei-Matcher hinzufügen, wie zum Beispiel nur für .php-Dateien.
Daniel Luca CleanUnicorn
98
KEIN SED VERWENDEN! Wenn eine Zeichenfolge eine eingebettete Registerkarte enthält, kann es sein, dass Sie Ihren Code beschädigen. Dies ist, was der Befehl expand behandeln sollte. Verwenden Sie expand.
David W.
5
@ DavidW. Ich würde diesen Befehl einfach aktualisieren, um nur Tabulatoren am Zeilenanfang zu ersetzen. find ./ -type f -exec sed -i 's/^\t/####/g' {} \;. Der Befehl expand war mir jedoch nicht bekannt - sehr nützlich!
Martin Konecny
29
VERWENDE NICHT! Diese Antwort hat auch gerade mein lokales Git-Repository zerstört. Wenn Sie Dateien mit gemischten Tabulatoren und Leerzeichen haben, werden Sequenzen von # eingefügt. Verwenden Sie stattdessen die Antwort von Gene oder den Kommentar von Doge unten.
Puppe
344
Ein einfacher Austausch durch sedist in Ordnung, aber nicht die bestmögliche Lösung. Wenn zwischen den Registerkarten "zusätzliche" Leerzeichen vorhanden sind, sind diese nach dem Ersetzen noch vorhanden, sodass die Ränder unregelmäßig sind. In der Mitte der Zeilen erweiterte Registerkarten funktionieren ebenfalls nicht richtig. In bashkönnen wir stattdessen sagen
auf expandjede Java-Datei im aktuellen Verzeichnisbaum anzuwenden . Entfernen / ersetzen Sie das -nameArgument, wenn Sie auf andere Dateitypen abzielen. Seien Sie, wie in einem der Kommentare erwähnt, sehr vorsichtig, wenn Sie -nameeinen schwachen Platzhalter entfernen oder verwenden. Sie können das Repository und andere versteckte Dateien problemlos ohne Absicht löschen. Aus diesem Grund enthielt die ursprüngliche Antwort Folgendes:
Sie sollten immer eine Sicherungskopie des Baums erstellen, bevor Sie so etwas versuchen, falls etwas schief geht.
@ JeffreyMartinez Gute Frage. gniourf_gniourf hat meine ursprüngliche Antwort am 11. November bearbeitet und abfällige Bemerkungen darüber gemacht, dass ich nicht weiß, wie ich sie richtig verwenden soll {}. Sieht so aus, als hätte er nicht gewusst, $0wann -ces verwendet wird. Dann änderte sich dimo414 von meiner Verwendung einer temporären Datei im Konvertierungsverzeichnis zu /tmp, die viel langsamer ist, wenn sie /tmpsich auf einem anderen Einhängepunkt befindet. Leider habe ich keine Linux-Box zur Verfügung, um Ihren $0Vorschlag zu testen . Aber ich denke du hast recht.
Gene
1
@Gene, danke für die Klarstellung, das klingt nach Stackoverflow in Ordnung: p. Während ich dabei bin, werde ich hinzufügen, dass ich Anführungszeichen um '* .java' verwenden musste, um die * .java richtig zu entkommen.
Jeffrey Martinez
2
Wenn jemand einen 'unbekannten Primär- oder Operator'-Fehler beim Finden hat, dann ist hier der vollständige Befehl, der ihn behebt:find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Doge
4
Ich dachte, diese Antwort hätte nicht genug Kommentare, also ist dies meine: Wenn Sie die Verwendung spongevon joeyh.name/code/moreutils verwenden , können Sie schreibenfind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
tokland
8
Sei nicht dumm und benutze find . -name '*', ich habe gerade mein lokales Git-Repo zerstört
Gautam
193
Probieren Sie das Befehlszeilenprogramm aus expand.
expand -i -t 4 input | sponge output
wo
-i wird verwendet, um nur führende Registerkarten in jeder Zeile zu erweitern.
-t 4 bedeutet, dass jede Registerkarte in 4 Leerzeichen umgewandelt wird (standardmäßig 8).
Sie sollten an übergeben -i, expandum nur führende Registerkarten in jeder Zeile zu ersetzen. Auf diese Weise wird vermieden, dass Registerkarten ersetzt werden, die möglicherweise Teil des Codes sind.
Quolonel Fragen
10
Wie wäre es für jede einzelne Datei in einem Verzeichnis rekursiv?
Ahnbizcad
4
Jedes Mal, wenn ich versuche, dies zu verwenden, werden einige (normalerweise alle) Dateien gelöscht. : \
ThorSummoner
5
@ThorSummoner: Wenn inputes sich um dieselbe Datei handelt wie outputdie Bash, wird der Inhalt bereits vor dem Start blockiert expand. So >funktioniert es.
Robert Siemer
34
Das Sammeln der besten Kommentare aus Gens Antwort , die mit Abstand beste Lösung, ist die Verwendung spongevon moreutils .
Sie können den allgemein verfügbaren prBefehl verwenden (Manpage hier ). Gehen Sie folgendermaßen vor, um Tabulatoren in vier Leerzeichen zu konvertieren:
pr -t -e=4 file > file.expanded
-t unterdrückt Header
-e=numErweitert Tabulatoren zu numLeerzeichen
So konvertieren Sie alle Dateien in einem Verzeichnisbaum rekursiv, während Sie Binärdateien überspringen:
#!/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
Die Logik zum Überspringen von Binärdateien stammt aus diesem Beitrag .
HINWEIS:
Dies könnte in einem Git oder SVN Repo gefährlich sein
Dies ist nicht die richtige Lösung, wenn Sie Codedateien haben, in die Registerkarten in Zeichenfolgenliteralen eingebettet sind
Gibt es einen Vorteil gegenüber der expandTatsache, dass beide POSIX sind? Hat es beispielsweise eine Inline-Änderungsoption? Git Sicherheit unter: stackoverflow.com/a/52136507/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 2
5
Wie kann ich Tabulatoren in Leerzeichen in jeder Datei eines Verzeichnisses konvertieren (möglicherweise rekursiv)?
Dies ist normalerweise nicht das, was Sie wollen.
Möchten Sie dies für PNG-Bilder tun? PDF-Dateien? Das .git-Verzeichnis? Ihre
Makefile(für die Tabs erforderlich sind )? Ein 5 GB SQL Dump?
Theoretisch könnten Sie eine ganze Reihe von Ausschlussoptionen an findoder was auch immer Sie sonst verwenden, übergeben. Dies ist jedoch fragil und wird unterbrochen, sobald Sie andere Binärdateien hinzufügen.
Was Sie wollen, ist zumindest:
Überspringen Sie Dateien über eine bestimmte Größe.
Ermitteln Sie, ob eine Datei binär ist, indem Sie prüfen, ob ein NULL-Byte vorhanden ist.
Ersetzen Sie Tabs nur am Anfang einer Datei ( expandtut dies, sed
tut es nicht).
Soweit ich weiß, gibt es kein "Standard" -Unix-Dienstprogramm, das dies kann, und es ist nicht sehr einfach, mit einem Shell-Einzeiler zu arbeiten, daher wird ein Skript benötigt.
Vor einiger Zeit habe ich ein kleines Skript namens
sanitize_files erstellt, das genau das tut. Es behebt auch einige andere häufig auftretende Probleme wie das Ersetzen \r\ndurch \n, das Hinzufügen eines Trailing \nusw.
Sie können ein vereinfachtes Skript ohne die zusätzlichen Funktionen und Befehlszeilenargumente finden, aber ich empfehle Ihnen, das obige Skript zu verwenden, da es mit größerer Wahrscheinlichkeit Bugfixes und andere aktualisierte als diesen Beitrag erhält.
Als Antwort auf einige der anderen Antworten möchte ich auch darauf hinweisen, dass die Verwendung von Shell-Globbing keine robuste Methode ist, da Sie früher oder später mehr Dateien haben, als in die ARG_MAXmoderne Version passen Linux-Systeme sind 128k, was viel zu sein scheint, aber früher oder später ist es nicht
genug).
#!/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)
Ich mag das Beispiel "find" oben für die rekursive Anwendung. Um es so anzupassen, dass es nicht rekursiv ist und nur Dateien im aktuellen Verzeichnis ändert, die einem Platzhalter entsprechen, kann die Shell-Glob-Erweiterung für kleine Mengen von Dateien ausreichen:
ls *.java | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}'| sh -v
Wenn Sie möchten, dass es stumm geschaltet wird, nachdem Sie darauf vertraut haben, dass es funktioniert, lassen Sie -vden shBefehl am Ende einfach fallen .
Natürlich können Sie im ersten Befehl einen beliebigen Satz von Dateien auswählen. Listen Sie beispielsweise nur ein bestimmtes Unterverzeichnis (oder Verzeichnisse) auf kontrollierte Weise wie folgt auf:
ls mod/*/*.php | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}'| sh
Oder führen Sie wiederum find (1) mit einer Kombination von Tiefenparametern usw .:
Das Shell-Globbing wird früher oder später unterbrochen, da die Gesamtanzahl der Dateinamen nur von ARG_MAXLänge sein kann. Auf Linux-Systemen sind dies 128 KB, aber ich habe diese Grenze oft genug erreicht, um mich nicht auf Shell-Globbing zu verlassen.
Martin Tournoij
1
Sie müssen sie nicht wirklich anpassen. findkann gesagt werden -maxdepth 1, und es verarbeitet nur die Einträge des Verzeichnisses, das geändert wird, nicht den gesamten Baum.
ShadowRanger
4
Ich habe astylemeinen gesamten C / C ++ - Code erneut eingerückt, nachdem ich gemischte Tabulatoren und Leerzeichen gefunden hatte. Es gibt auch Optionen, um einen bestimmten Klammerstil zu erzwingen, wenn Sie möchten.
Wie Carpetsmoker angegeben hat, wird es gemäß Ihren vimEinstellungen retab . Und Modelines in den Dateien, falls vorhanden. Außerdem werden Registerkarten nicht nur am Zeilenanfang ersetzt. Welches ist nicht das, was Sie im Allgemeinen wollen. Beispielsweise könnten Sie Literale haben, die Tabulatoren enthalten.
:retabändert alle Registerkarten in einer Datei, nicht die am Anfang. es hängt auch davon ab , was Ihre :tabstopund :expandtabEinstellungen sind in den vimrc oder Modeline , so kann dies überhaupt nicht arbeiten.
Martin Tournoij
@Carpetsmoker Guter Punkt zu Tabs am Zeilenanfang. Behandelt eine der hier aufgeführten Lösungen diesen Fall? Was die tabstopund expandtabEinstellungen betrifft, wird es funktionieren, wenn Sie verwenden vim. Es sei denn, Sie haben Moduszeilen in den Dateien.
X-Yuri
@ x-yuri gute Frage, aber im Allgemeinen strittig. Die meisten Leute verwenden keine tatsächlichen Tabulatoren in Literalen.
Ricardo Cruz
4
Meine Empfehlung ist zu verwenden:
find .-name '*.lua'-exec ex '+%s/\t/ /g'-cwq {} \;
Bemerkungen:
Verwenden Sie die In-Place-Bearbeitung. Bewahren Sie Backups in einem VCS auf. Es müssen keine * .orig-Dateien erstellt werden. Es ist empfehlenswert, das Ergebnis von Ihrem letzten Commit zu unterscheiden, um sicherzustellen, dass dies auf jeden Fall wie erwartet funktioniert.
sedist ein Stream-Editor. Verwenden Sie exfür die an Ort und Stelle bearbeiten. Dadurch wird vermieden, dass für jeden Ersatz zusätzliche temporäre Dateien und Spawning-Shells wie in der oberen Antwort erstellt werden .
WARNUNG: Dies beeinträchtigt alle Registerkarten, nicht nur die zum Einrücken verwendeten. Außerdem werden keine Registerkarten kontextsensitiv ersetzt. Dies war ausreichend für meinen Anwendungsfall. Aber vielleicht nicht akzeptabel für Sie.
BEARBEITEN: Eine frühere Version dieser Antwort wird find|xargsanstelle von verwendet find -exec. Wie von @ gniourf-gniourf hervorgehoben, führt dies zu Problemen mit Leerzeichen, Anführungszeichen und Steuerzeichen in Dateinamen, vgl. Wheeler .
exist möglicherweise nicht auf jedem Unix-System verfügbar. Das Ersetzen durch vi -ekönnte auf mehr Maschinen funktionieren. Außerdem ersetzt Ihre Regex eine beliebige Anzahl von Zeichen auf der Startregisterkarte durch zwei Leerzeichen. Ersetzen Sie den regulären Ausdruck durch +%s/\t/ /g, ohne die mehrstufige Einrückung zu zerstören. Dies betrifft jedoch auch Tabulatorzeichen, die nicht zum Einrücken verwendet werden.
Lukas Schmelzeisen
ex ist Teil von POSIX [1] und sollte daher verfügbar sein. Guter Punkt zur mehrstufigen Indendation. Ich hatte die /\t/ /Variante tatsächlich für meine Dateien verwendet, mich jedoch dafür entschieden /\t\+//, nicht einrückende Registerkarten nicht zu beschädigen. Verpasste die Probleme mit Multi-Indentation! Antwort aktualisieren. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSO
Heinrich Hartmann
2
Die Verwendung xargsauf diese Weise ist nutzlos, ineffizient und fehlerhaft (denken Sie an Dateinamen, die Leerzeichen oder Anführungszeichen enthalten). Warum Sie nicht verwenden find‚s - -execOption statt?
gniourf_gniourf
Ich würde argumentieren, dass Dateinamen mit Leerzeichen und Anführungszeichen fehlerhaft sind. ) Wenn Sie das unterstützen müssen, würde ich mich entscheiden für: -print0Optionen zum Finden von / xargs. Ich mag xargs -execseit: a) Trennung von Bedenken b) es kann leichter mit GNU parallel ausgetauscht werden.
Heinrich Hartmann
Das Hinzufügen von @ gniourf_gniourf-Kommentaren wurde aktualisiert.
Heinrich Hartmann
4
So konvertieren Sie alle Java-Dateien rekursiv in ein Verzeichnis, um 4 Leerzeichen anstelle einer Registerkarte zu verwenden:
Wie wird diese Antwort unterscheidet sich von dieser , die wurde vor 4 Jahren geschrieben?
PP
2
Ihre Antwort auch. Tatsächlich ist dies eine minderwertige Version von Gens Antwort: 1) Gens Antwort kümmert sich um Verzeichnisse mit demselben Namen. 2) Es bewegt sich nicht , wenn die Erweiterung fehlgeschlagen ist.
PP
4
Sie können findmit verwendentabs-to-spaces Paket dafür verwenden.
Installieren Sie zuerst tabs-to-spaces
npm install -g tabs-to-spaces
Führen Sie diesen Befehl dann im Stammverzeichnis Ihres Projekts aus.
find .-name '*'-exec t2s --spaces 2{} \;
Dadurch wird jedes tabZeichen spacesin jeder Datei durch 2 ersetzt .
Dies hat alle Binärdateien in meinem Repo beschädigt.
Aaron Franke
1
Ein ausgezeichneter Befehl, aber möglicherweise gefährlich mit der oben angegebenen Option für rekursive und alle Dateien im Ordner. Ich würde die Option --dry-run "nur für den Fall" hinzufügen, um sicherzustellen, dass Sie im richtigen Ordner sitzen.
MortimerCat
2
Die Verwendung von, expandwie in anderen Antworten vorgeschlagen, scheint der logischste Ansatz für diese Aufgabe allein zu sein.
Dies kann jedoch auch mit Bash und Awk durchgeführt werden, falls Sie weitere Änderungen vornehmen möchten.
Wenn Sie Bash 4.0 oder höher verwenden, können Sie mit dem integrierten shoptglobstar rekursiv suchen **.
Mit GNU Awk Version 4.1 oder höher können sed-ähnliche "Inplace" -Dateimodifikationen vorgenommen werden:
Laden Sie das folgende Skript herunter und führen Sie es aus, um harte Registerkarten in Nur-Text-Dateien rekursiv in weiche Registerkarten zu konvertieren.
Führen Sie das Skript in dem Ordner aus, der die Nur-Text-Dateien enthält.
Offensichtlich hängt der Speicherplatz, auf den eine Registerkarte erweitert wird, vom Kontext ab. Sed ist daher ein völlig ungeeignetes Werkzeug für die Aufgabe.
Sven
?? @Sven, mein sed Befehl macht das gleiche wie der Befehl expand ( expand -t 4 input >output)
Makah
3
Natürlich nicht. expand -t 4Erweitert die Registerkarte a\tbauf 3 Felder und die Registerkarte aa\tbauf 2 Felder, so wie es sein sollte. expandBerücksichtigt den Kontext einer Registerkarte, sedersetzt die Registerkarte nicht und ersetzt sie durch die von Ihnen angegebene Anzahl von Leerzeichen, unabhängig vom Kontext.
Sven
-1
Verwenden Sie den vim-Weg:
$ ex +'bufdo retab'-cxa **/*.*
Machen Sie das Backup! bevor Sie den obigen Befehl ausführen, da er Ihre Binärdateien beschädigen kann.
Um globstar( **) für die Rekursion zu verwenden, aktivieren Sie durch shopt -s globstar.
Verwenden Sie zum Festlegen eines bestimmten Dateityps beispielsweise : **/*.c.
Fügen Sie hinzu, um Tabstop zu ändern +'set ts=2'.
... und alle Ihre Lösungen werden Binärdateien und dergleichen (wie PNG-Dateien, PDF-Dateien usw.)
überfallen
Dies ist offen gesagt ein schrecklicher Vorschlag für die Dokumentation - man muss mit einer Reihe von ziemlich undurchsichtigen Syntax- und Semantikproblemen mehrerer Programme vertraut sein, um dies verstehen zu können.
pr
ist ein wunderbarer Nutzen dafür. Siehe diese Antwort .Antworten:
find . -iname '*.java' -type f -exec sed -i.orig 's/\t/ /g' {} +
Die Originaldatei wird als gespeichert
[filename].orig
.Ersetzen Sie '* .java' durch das Dateiende des gesuchten Dateityps. Auf diese Weise können Sie eine versehentliche Beschädigung von Binärdateien verhindern.
Nachteile:
quelle
expand
.find ./ -type f -exec sed -i 's/^\t/####/g' {} \;
. Der Befehl expand war mir jedoch nicht bekannt - sehr nützlich!Ein einfacher Austausch durch
sed
ist in Ordnung, aber nicht die bestmögliche Lösung. Wenn zwischen den Registerkarten "zusätzliche" Leerzeichen vorhanden sind, sind diese nach dem Ersetzen noch vorhanden, sodass die Ränder unregelmäßig sind. In der Mitte der Zeilen erweiterte Registerkarten funktionieren ebenfalls nicht richtig. Inbash
können wir stattdessen sagenauf
expand
jede Java-Datei im aktuellen Verzeichnisbaum anzuwenden . Entfernen / ersetzen Sie das-name
Argument, wenn Sie auf andere Dateitypen abzielen. Seien Sie, wie in einem der Kommentare erwähnt, sehr vorsichtig, wenn Sie-name
einen schwachen Platzhalter entfernen oder verwenden. Sie können das Repository und andere versteckte Dateien problemlos ohne Absicht löschen. Aus diesem Grund enthielt die ursprüngliche Antwort Folgendes:quelle
{}
. Sieht so aus, als hätte er nicht gewusst,$0
wann-c
es verwendet wird. Dann änderte sich dimo414 von meiner Verwendung einer temporären Datei im Konvertierungsverzeichnis zu/tmp
, die viel langsamer ist, wenn sie/tmp
sich auf einem anderen Einhängepunkt befindet. Leider habe ich keine Linux-Box zur Verfügung, um Ihren$0
Vorschlag zu testen . Aber ich denke du hast recht.find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
sponge
von joeyh.name/code/moreutils verwenden , können Sie schreibenfind . -name '*.py' ! -type d -exec bash -c 'expand -t 8 "$0" | sponge "$0"' {} \;
find . -name '*'
, ich habe gerade mein lokales Git-Repo zerstörtProbieren Sie das Befehlszeilenprogramm aus
expand
.wo
-i
wird verwendet, um nur führende Registerkarten in jeder Zeile zu erweitern.-t 4
bedeutet, dass jede Registerkarte in 4 Leerzeichen umgewandelt wird (standardmäßig 8).sponge
ist aus demmoreutils
Paket und vermeidet das Löschen der Eingabedatei .Schließlich können Sie es
gexpand
nach der Installationcoreutils
mit Homebrew (brew install coreutils
) unter OSX verwenden .quelle
-i
,expand
um nur führende Registerkarten in jeder Zeile zu ersetzen. Auf diese Weise wird vermieden, dass Registerkarten ersetzt werden, die möglicherweise Teil des Codes sind.input
es sich um dieselbe Datei handelt wieoutput
die Bash, wird der Inhalt bereits vor dem Start blockiertexpand
. So>
funktioniert es.Das Sammeln der besten Kommentare aus Gens Antwort , die mit Abstand beste Lösung, ist die Verwendung
sponge
von moreutils .Erläuterung:
./
sucht rekursiv aus dem aktuellen Verzeichnis-iname
ist eine Übereinstimmung ohne Berücksichtigung der Groß- und Kleinschreibung (für beide*.java
und*.JAVA
Likes)type -f
findet nur reguläre Dateien (keine Verzeichnisse, Binärdateien oder Symlinks)-exec bash -c
Führen Sie für jeden Dateinamen die folgenden Befehle in einer Unterschale aus:{}
expand -t 4
erweitert alle TABs auf 4 Leerzeichensponge
Nehmen Sie die Standardeingabe (vonexpand
) auf und schreiben Sie in eine Datei (dieselbe) *.HINWEIS : * Eine einfache Dateiumleitung (
> "$0"
) funktioniert hier nicht, da die Datei zu früh überschrieben wird .Vorteil : Alle ursprünglichen Dateiberechtigungen bleiben erhalten und es werden keine Zwischendateien
tmp
verwendet.quelle
Verwenden Sie Backslash-Escape
sed
.Unter Linux:
Ersetzen Sie alle Registerkarten in allen * .txt-Dateien durch einen Bindestrich:
Ersetzen Sie alle Registerkarten in allen * .txt-Dateien durch 1 Leerzeichen:
Ersetzen Sie alle Registerkarten durch 4 Leerzeichen in allen * .txt-Dateien:
Auf einem Mac:
Ersetzen Sie alle Registerkarten durch 4 Leerzeichen in allen * .txt-Dateien:
quelle
sed -i '' $'s/\t/ /g' $(find . -name "*.txt")
Sie können den allgemein verfügbaren
pr
Befehl verwenden (Manpage hier ). Gehen Sie folgendermaßen vor, um Tabulatoren in vier Leerzeichen zu konvertieren:-t
unterdrückt Header-e=num
Erweitert Tabulatoren zunum
LeerzeichenSo konvertieren Sie alle Dateien in einem Verzeichnisbaum rekursiv, während Sie Binärdateien überspringen:
Die Logik zum Überspringen von Binärdateien stammt aus diesem Beitrag .
HINWEIS:
quelle
expand
Tatsache, dass beide POSIX sind? Hat es beispielsweise eine Inline-Änderungsoption? Git Sicherheit unter: stackoverflow.com/a/52136507/895245Dies ist normalerweise nicht das, was Sie wollen.
Möchten Sie dies für PNG-Bilder tun? PDF-Dateien? Das .git-Verzeichnis? Ihre
Makefile
(für die Tabs erforderlich sind )? Ein 5 GB SQL Dump?Theoretisch könnten Sie eine ganze Reihe von Ausschlussoptionen an
find
oder was auch immer Sie sonst verwenden, übergeben. Dies ist jedoch fragil und wird unterbrochen, sobald Sie andere Binärdateien hinzufügen.Was Sie wollen, ist zumindest:
expand
tut dies,sed
tut es nicht).Soweit ich weiß, gibt es kein "Standard" -Unix-Dienstprogramm, das dies kann, und es ist nicht sehr einfach, mit einem Shell-Einzeiler zu arbeiten, daher wird ein Skript benötigt.
Vor einiger Zeit habe ich ein kleines Skript namens sanitize_files erstellt, das genau das tut. Es behebt auch einige andere häufig auftretende Probleme wie das Ersetzen
\r\n
durch\n
, das Hinzufügen eines Trailing\n
usw.Sie können ein vereinfachtes Skript ohne die zusätzlichen Funktionen und Befehlszeilenargumente finden, aber ich empfehle Ihnen, das obige Skript zu verwenden, da es mit größerer Wahrscheinlichkeit Bugfixes und andere aktualisierte als diesen Beitrag erhält.
Als Antwort auf einige der anderen Antworten möchte ich auch darauf hinweisen, dass die Verwendung von Shell-Globbing keine robuste Methode ist, da Sie früher oder später mehr Dateien haben, als in die
ARG_MAX
moderne Version passen Linux-Systeme sind 128k, was viel zu sein scheint, aber früher oder später ist es nicht genug).quelle
Ich mag das Beispiel "find" oben für die rekursive Anwendung. Um es so anzupassen, dass es nicht rekursiv ist und nur Dateien im aktuellen Verzeichnis ändert, die einem Platzhalter entsprechen, kann die Shell-Glob-Erweiterung für kleine Mengen von Dateien ausreichen:
Wenn Sie möchten, dass es stumm geschaltet wird, nachdem Sie darauf vertraut haben, dass es funktioniert, lassen Sie
-v
densh
Befehl am Ende einfach fallen .Natürlich können Sie im ersten Befehl einen beliebigen Satz von Dateien auswählen. Listen Sie beispielsweise nur ein bestimmtes Unterverzeichnis (oder Verzeichnisse) auf kontrollierte Weise wie folgt auf:
Oder führen Sie wiederum find (1) mit einer Kombination von Tiefenparametern usw .:
quelle
ARG_MAX
Länge sein kann. Auf Linux-Systemen sind dies 128 KB, aber ich habe diese Grenze oft genug erreicht, um mich nicht auf Shell-Globbing zu verlassen.find
kann gesagt werden-maxdepth 1
, und es verarbeitet nur die Einträge des Verzeichnisses, das geändert wird, nicht den gesamten Baum.Ich habe
astyle
meinen gesamten C / C ++ - Code erneut eingerückt, nachdem ich gemischte Tabulatoren und Leerzeichen gefunden hatte. Es gibt auch Optionen, um einen bestimmten Klammerstil zu erzwingen, wenn Sie möchten.quelle
Man kann dafür verwenden
vim
:Wie Carpetsmoker angegeben hat, wird es gemäß Ihren
vim
Einstellungen retab . Und Modelines in den Dateien, falls vorhanden. Außerdem werden Registerkarten nicht nur am Zeilenanfang ersetzt. Welches ist nicht das, was Sie im Allgemeinen wollen. Beispielsweise könnten Sie Literale haben, die Tabulatoren enthalten.quelle
:retab
ändert alle Registerkarten in einer Datei, nicht die am Anfang. es hängt auch davon ab , was Ihre:tabstop
und:expandtab
Einstellungen sind in den vimrc oder Modeline , so kann dies überhaupt nicht arbeiten.tabstop
undexpandtab
Einstellungen betrifft, wird es funktionieren, wenn Sie verwendenvim
. Es sei denn, Sie haben Moduszeilen in den Dateien.Meine Empfehlung ist zu verwenden:
Bemerkungen:
sed
ist ein Stream-Editor. Verwenden Sieex
für die an Ort und Stelle bearbeiten. Dadurch wird vermieden, dass für jeden Ersatz zusätzliche temporäre Dateien und Spawning-Shells wie in der oberen Antwort erstellt werden .find|xargs
anstelle von verwendetfind -exec
. Wie von @ gniourf-gniourf hervorgehoben, führt dies zu Problemen mit Leerzeichen, Anführungszeichen und Steuerzeichen in Dateinamen, vgl. Wheeler .quelle
ex
ist möglicherweise nicht auf jedem Unix-System verfügbar. Das Ersetzen durchvi -e
könnte auf mehr Maschinen funktionieren. Außerdem ersetzt Ihre Regex eine beliebige Anzahl von Zeichen auf der Startregisterkarte durch zwei Leerzeichen. Ersetzen Sie den regulären Ausdruck durch+%s/\t/ /g
, ohne die mehrstufige Einrückung zu zerstören. Dies betrifft jedoch auch Tabulatorzeichen, die nicht zum Einrücken verwendet werden./\t/ /
Variante tatsächlich für meine Dateien verwendet, mich jedoch dafür entschieden/\t\+//
, nicht einrückende Registerkarten nicht zu beschädigen. Verpasste die Probleme mit Multi-Indentation! Antwort aktualisieren. [1] man7.org/linux/man-pages/man1/ex.1p.html#SEE%C2%A0ALSOxargs
auf diese Weise ist nutzlos, ineffizient und fehlerhaft (denken Sie an Dateinamen, die Leerzeichen oder Anführungszeichen enthalten). Warum Sie nicht verwendenfind
‚s --exec
Option statt?-print0
Optionen zum Finden von / xargs. Ich mag xargs-exec
seit: a) Trennung von Bedenken b) es kann leichter mit GNU parallel ausgetauscht werden.So konvertieren Sie alle Java-Dateien rekursiv in ein Verzeichnis, um 4 Leerzeichen anstelle einer Registerkarte zu verwenden:
quelle
Sie können
find
mit verwendentabs-to-spaces
Paket dafür verwenden.Installieren Sie zuerst
tabs-to-spaces
Führen Sie diesen Befehl dann im Stammverzeichnis Ihres Projekts aus.
Dadurch wird jedes
tab
Zeichenspaces
in jeder Datei durch 2 ersetzt .quelle
Kein Körper erwähnt
rpl
? Mit rpl können Sie eine beliebige Zeichenfolge ersetzen. Um Tabulatoren in Leerzeichen umzuwandeln,sehr einfach.
quelle
Die Verwendung von,
expand
wie in anderen Antworten vorgeschlagen, scheint der logischste Ansatz für diese Aufgabe allein zu sein.Dies kann jedoch auch mit Bash und Awk durchgeführt werden, falls Sie weitere Änderungen vornehmen möchten.
Wenn Sie Bash 4.0 oder höher verwenden, können Sie mit dem integrierten shopt
globstar
rekursiv suchen**
.Mit GNU Awk Version 4.1 oder höher können sed-ähnliche "Inplace" -Dateimodifikationen vorgenommen werden:
Wenn Sie die Anzahl der Leerzeichen pro Registerkarte festlegen möchten:
quelle
Laden Sie das folgende Skript herunter und führen Sie es aus, um harte Registerkarten in Nur-Text-Dateien rekursiv in weiche Registerkarten zu konvertieren.
Führen Sie das Skript in dem Ordner aus, der die Nur-Text-Dateien enthält.
quelle
Git Repository freundliche Methode
Auf alle Dateien im aktuellen Verzeichnis einwirken:
Nur auf C- oder C ++ - Dateien einwirken:
Sie möchten dies wahrscheinlich vor allem wegen der nervigen Makefiles, für die Registerkarten erforderlich sind.
Der Befehl
git grep --cached -Il ''
:.git
wie unter erklärt: Wie liste ich alle Textdateien (nicht binär) in einem Git-Repository auf?
chmod --reference
behält die Dateiberechtigungen unverändert bei: /unix/20645/clone-ownership-and-permissions-from-another-file Leider kann ich keine prägnante POSIX-Alternative finden .Wenn Ihre Codebasis die verrückte Idee hatte, funktionale unformatierte Registerkarten in Zeichenfolgen zuzulassen, verwenden Sie:
und dann viel Spaß beim Durchgehen aller Registerkarten ohne Zeilenanfang nacheinander, die Sie auflisten können mit: Ist es möglich, grep für Tabs zu aktivieren?
Getestet unter Ubuntu 18.04.
quelle
Konvertieren von Tabulatoren in Leerzeichen nur in ".lua" -Dateien [Tabulatoren -> 2 Leerzeichen]
quelle
expand -t 4 input >output
)expand -t 4
Erweitert die Registerkartea\tb
auf 3 Felder und die Registerkarteaa\tb
auf 2 Felder, so wie es sein sollte.expand
Berücksichtigt den Kontext einer Registerkarte,sed
ersetzt die Registerkarte nicht und ersetzt sie durch die von Ihnen angegebene Anzahl von Leerzeichen, unabhängig vom Kontext.Verwenden Sie den vim-Weg:
globstar
(**
) für die Rekursion zu verwenden, aktivieren Sie durchshopt -s globstar
.**/*.c
.Fügen Sie hinzu, um Tabstop zu ändern
+'set ts=2'
.Der Nachteil ist jedoch, dass es Tabs innerhalb der Zeichenfolgen ersetzen kann .
Versuchen Sie für eine etwas bessere Lösung (durch Substitution):
Oder mit
ex
Editor +expand
Dienstprogramm:Informationen zu nachgestellten Leerzeichen finden Sie unter: So entfernen Sie nachfolgende Leerzeichen für mehrere Dateien.
Sie können Ihrer Funktion folgende Funktion hinzufügen
.bash_profile
:quelle
:retab
funktioniert möglicherweise überhaupt nicht , Shell Globbing ist eine schlechte Lösung für diese Art von Dingen , Ihr:s
Befehl ersetzt eine beliebige Anzahl von Tabulatoren durch 2 Leerzeichen (was Sie fast tun nie wollen), ex nur zu starten, um einen:!expand
Prozess auszuführen , ist dumm ...