私は極端な問題を抱えており、想像できるすべての解決策は複雑です。私のUNIX/Linuxの経験によるとmustは簡単な方法です。
/foo/
の各ファイルの最初の31バイトを削除したい。各ファイルは十分に長いです。まあ、私が想像もできない驚くほど簡単なソリューションを誰かが私に届けてくれると確信しています。多分awk?
for file in /foo/*
do
if [ -f "$file" ]
then
dd if="$file" of="$file.truncated" bs=31 skip=1 && mv "$file.truncated" "$file"
fi
done
またはGillesの提案のおかげでより速く:
for file in /foo/*
do
if [ -f $file ]
then
tail +32c $file > $file.truncated && mv $file.truncated $file
fi
done
注:Posixテールは「+ 32c」ではなく「-c +32」を指定しますが、Solarisのデフォルトテールはそれを好みません。
$ /usr/bin/tail -c +32 /tmp/foo > /tmp/foo1
tail: cannot open input
/usr/xpg4/bin/tail
は両方の構文で問題ありません。
次のコマンドは、$file
から最初の31バイトを切り取ります($file~
を一時コピーとして使用)。
dd if="$file" of="$file~" bs=1 skip=31
mv "$file~" "$file"
/foo/
の下にあるすべてのファイルをリストまたはfind
し、$file
が検出されるたびに上記の2つを実行する必要があります。
tail -c +32
は、その入力から最初の31バイトを引いた値を出力します。 (はい、引数は1ずつずれています。)ファイルをその場で編集するには、ループで se sponge を使用します。または、ファイルがなく、気になりたくない場合は、そのジョブを実行します。シェルで:
for x in /foo/*; do tail -c +32 "$x" | sponge "$x"; done
for x in /foo/*; do tail -c +32 "$x" >"$x.new" && mv "$x.new" "$x"; done
なんらかの理由(停電など)でコマンドが中断された場合、中断した場所を特定するのが難しい場合があります。新しいファイルを別のディレクトリに書き込むと、状況が簡単になります。
mkdir /foo.tmp
cd /foo
for x in *; do tail -c +42 -- "$x" >"/foo.tmp/$x" && rm -- "$x"; done
mv /foo.tmp/* /foo
rmdir /foo.tmp
ファイルが本当に大きい場合(たとえば、1つのコピーでも2つのコピーがあることが問題になるほど大きい場合)、 このスレッドで言及されている手法の1つ を使用できます。
VimはExモードで使用できます。
for each in /foo/*
do
ex -sc '%!tail -c+32' -cx "$each"
done
%
すべての行を選択
!
runコマンド
x
保存して閉じる