私は現在、次の 簡略化されたコマンド から末尾の空白を削除およびファイルの最後に改行を追加必要に応じて使用しています。
find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+
すぐにわかるように、これには2つの問題があります。変更されるバイナリファイルと、ファイルの末尾に␍␊行区切り記号で改行が追加されます。これらの変更は、git gui
などでコミットするときに簡単に元に戻したりスキップしたりできますが、元に戻す量を最小限に抑えたい*と思います。そのために:
any行がsed
の正規表現と一致する場合、wholeファイルをスキップする方法はありますか?
*␀文字のないバイナリファイルが存在する可能性があること、および意図的に改行または␀が混在するファイルが存在する可能性があることを認識しています。しかし、私は最小限の人間の介入を必要とする解決策を探しています。 I couldおそらく、操作したいすべてのファイル拡張子をリストしますが、それは非常に長いリストであり、絶えず見直す必要があり、名前の衝突のためにそれでも可能です。そのバイナリファイルはすり抜けます。
複雑 回避策 :
while IFS= read -r -d '' -u 9
do
if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
then
sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' -- "$REPLY"
else
echo "Skipping $REPLY" >&2
fi
done 9< <(find . -type f -print0)
バイナリファイルとは何かについてgit
の観点を信頼している場合は、git grep
を使用して非バイナリファイルのリストを取得できます。 t.cpp
がテキストファイルであり、ls
がバイナリであると仮定すると、両方ともチェックインされます。
$ ls
t.cpp ls
$ git grep -I --name-only -e ''
t.cpp
-I
オプションの意味:
-I
バイナリファイルのパターンと一致しないでください。
これをsed
式と組み合わせるには:
$ git grep -I --name-only -z -e '' | \
xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\'
(-z
/xargs -0
は、奇妙なファイル名を支援します。)
その他の便利なオプションについては、git grep
のマニュアルページを確認してください。--no-index
または--cached
は、操作するファイルのセットに応じて役立つ場合があります。
Sedの正規表現に一致する行がある場合にファイル全体をスキップする方法はありますか?
はいあります。
# test case for skipping file if a sed regex match succeeds
echo 'Hello, world!' > hello_world.txt
cat hello_world.txt
ls -li hello_world.txt
sed -i -e '/.*Hello.*/{q;}; s/world/WORLD/g' hello_world.txt # skips file
sed -i -e '/.*HeLLo.*/{q;}; s/world/WORLD/g' hello_world.txt
これは、引数(ファイル名である必要があります)を反復処理し、改行で終わらないすべてのファイルに改行を追加するPerlスクリプトです。 nullバイトを含むファイルはスキップされます。すでに改行で終わっているファイルは変更されません。 CRを含むファイルにはCRLFが追加され、その他のファイルにはLFのみが追加されます。テストされていません。
#!/usr/bin/env Perl
foreach my $f (@ARGV) {
open F, "<", $f or die;
my $last = undef;
my $cr = 0;
while (<>) {if (/\0/) {undef $last; break} $last = $_; ++$cr if /\r$/}
close F;
if (defined $last && $last !~ /\n\Z/) {
open F, ">>", $f or die;
print($cr ? "\r\n" : "\n");
close F or die;
}
}