現在、以下を使用しています簡略化されたコマンド到着末尾のスペースを削除そしてファイルの末尾に改行文字を追加する必要な場合:
find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+
すぐにわかりますが、ここには2つの問題があります。バイナリファイルファイルの末尾に改行文字を追加します。␍␊ 行区切り記号。コミットまたは同様の場合、これらの修正は簡単に元に戻すかスキップされますが、回復量を最小限に抑えたいとgit gui
思います。そのために:
スキップする方法はありますか?みんな次の場合はファイルを送信してください。どの行はsed
? の正規表現と一致します。
* ␀文字のないバイナリがある可能性があり、意図的に改行や␀文字を混ぜたファイルがある可能性があることを知っています。しかし、私は人の介入を最小限に抑えるソリューションを探しています。私できる作業したいすべてのファイル拡張子を一覧表示することは可能ですが、これは絶えず確認する必要がある非常に長いリストになり、名前の競合によってバイナリがなくなる可能性があります。
複雑解決策:
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)
答え1
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
作業したいファイルセットに応じて役立つことがあります。
答え2
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
答え3
以下は、引数(ファイル名でなければならない)を繰り返し、改行で終わらない各ファイルに改行を追加する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;
}
}