多くのファイルでタブをスペースに変換する


11

タブが散らばっているファイルがたくさんあるので、それらをすべてスペースに変換したいと思います。このexpandコマンドについては知っていますが、残念ながら、それを使用してすべてのファイルを入力する必要があります。Linuxでこれを行う簡単な方法はありますか?

回答:


12

以下を試してください:

find ./ -type f -exec sed -i 's/\t/ /g' {} \;

4つのスペースが必要な場合は、次を試してください。

find ./ -type f -exec sed -i 's/\t/    /g' {} \;

これにより、各タブが単一のスペースに置き換えられます。を使用して言及したのでexpand、私はs / heがテキストの配置を保持することを望んでいると仮定します。
ゲイリージョン

's/\t/ /g'1行につき複数のタブを置き換える必要があります。
ダニエルアンダーソン

1
多くのファイルが存在する場合の大幅な高速化は、「find ./ -type f -exec sed -i ’s/\t/ /g’ {} +」(つまり、「+」の代わりに「\;」)、findバージョンがサポートしている場合(およびサポートしていないバージョンに個人的に出会ったことがないが、POSIX標準ではない場合) 、そのため、一部のシステムで発生する可能性があります。-exec command {} +マニュアルの「」を参照してください。代わりの1つのインスタンスを起動するとsed、すべてのファイルに対して、これはと引数リストを構築するシステムのサポート(など、多くのファイル名引数としてgetconf ARG_MAXだけのように私のシステム上= 2097152)、xargsので、起動ずっと少ないsedプロセス。
ダニエルアンダーソン

6
これを見つけたMacユーザーへの注意:OS Xのバージョンはsed\tタブエスケープシーケンスを理解していません。これをリテラルのタブ文字に置き換えることができます。これは、シェルで入力できます[Ctrl]+V, [Tab]
ジェレミー銀行


6

これを行うには多くの方法があります。注意を怠ったり、見た目でLinuxを初めて使用する場合は、これを行いながら自分自身を撃つ方法もたくさんあります。のようなものを使用するかfind、エディターを使用して手動で変換するファイルのリストを作成できると仮定して、そのリストを次のようにパイプします。

while read file
do
   expand "$file" > /tmp/expandtmp
   mv /tmp/expandtmp "$file"
done

自分の足で撃つことができる1つの方法は、タイプミスをして、指定したすべてのファイル名に空のファイルをmv'ingして、すべてのファイルの内容を削除することです。したがって、バックアップした小さなファイルセットで最初に行うことを慎重にテストしてください。


3
作るmvの成功を条件expandexpand ... && mv ...
追って通知があるまで一時停止しました。

expand -t 4タブを4つのスペースに展開することを忘れないでください。また、このメソッドは末尾の改行を作成できます。しかし、そうでなければ機能します。
mgold 14

3
find . -type f -iname "*.js" -print0 | xargs -0 -I foo tab2space foo foo

-I foo 入力行ごとにテンプレート変数fooを作成するため、入力を複数回参照できます。

-print0また-0、スペースの代わりに\ 0を行区切り文字として使用するように両方のコマンドに指示するため、このコマンドはスペースを含むパスに対して機能します。


1
find -name \*.js -exec bash -c 'expand -t 4 "$0" | tee "$0"' {} \;

短所:
パイプバッファーサイズ(64KB)より大きいファイルは切り捨てられます

長所: パイプバッファーサイズよりも大きい
一時ファイル
は切り捨てられません


0

これの方が良い:

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

3
なぜこれが良いのですか?/tmp/e他の何かがそのファイルを使用している場合、これはそれを台無しにするので、使用することは素晴らしいアイデアではありません。2人のユーザーが同時にこれを使用したい場合のように。
ケビンパンコ14年

0

この問題に、次の要件を念頭に置いて試してみました。

  • 名前に基づいてファイルをフィルタリングし、たとえば.cppまたは.jsonファイルのみを処理します
  • 並列処理をサポートします。多くのファイルがある場合、これは非常に高速化を提供できます
  • ソリューションは使いやすいように1行に収まる必要があります

最後の要件は、「展開」では所定の場所にあるファイルを変更できないため、満たすのが最も困難でした。

私は次の解決策を思いつきました:

find . -type f -regextype egrep -regex '.*\.(c|cpp|h|hpp)'  -print0 | xargs -0 -n 1 -P 10 -IFILE bash -c ' ( echo "Processing FILE..." && expand -t 4 "FILE" > /tmp/expand.$$ && mv /tmp/expand.$$ "FILE" ) || exit 255'

以下に説明を示します。

  • 「find」は、処理するファイルを見つけます。「-regextype egrep」では、名前と「egrep」形式の正規表現に基づいてフィルタリングできます。
  • 「-type f」パラメータは、インスタンスディレクトリやその他の特別なものではなく、通常のファイルのみに一致するようにします
  • 「-regexp」パラメーターは正規表現そのものです。この場合、.c、.cpp、.h、または.hppで終わるすべてのファイルに一致します(名前全体が一致する必要があるため、「file.c2」は一致しません) 、私たちが望むものです)
  • 「-print0」は、「find」に指示して、各パスの末尾に文字0​​を付けて標準出力にファイルパスを印刷します。「xargs」のオプション「-0」と一緒に使用すると、1つのツールから別のツールに復帰キャリッジを含む名前を渡すことができます(非常にまれな状況であっても...)
  • xargsは、各パスに対して新しいプロセスを開始します(「-n 1」)が、最大10プロセスを並行して実行できます(「-P 10」)
  • xargsはエイリアス「FILE」を使用して、各ファイルパスをコマンドに渡します。これはbashスクリプトです
  • bashスクリプトは「expand」を呼び出して、現在のプロセスID($$)を含む名前の一時ファイルに結果を保存します。これにより、特定のファイルで並行して実行されるすべてのプロセスが異なる一時ファイルを使用します。
  • コマンド全体がパターン(command1 && command2 && command3)を使用するため、サブコマンドがエラーを返した場合、プロセスは停止します
  • 前の「&&」チェーンからエラーが発生した場合、bashスクリプトは終了コード255を返し、xargsがすぐに停止します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.