web-dev-qa-db-ja.com

ファイルの最初のnバイトを削除する

私は極端な問題を抱えており、想像できるすべての解決策は複雑です。私のUNIX/Linuxの経験によるとmustは簡単な方法です。

/foo/の各ファイルの最初の31バイトを削除したい。各ファイルは十分に長いです。まあ、私が想像もできない驚くほど簡単なソリューションを誰かが私に届けてくれると確信しています。多分awk?

32
von der tann
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は両方の構文で問題ありません。

28
jlliagre

次のコマンドは、$fileから最初の31バイトを切り取ります($file~を一時コピーとして使用)。

dd if="$file" of="$file~" bs=1 skip=31
mv "$file~" "$file"

/foo/の下にあるすべてのファイルをリストまたはfindし、$fileが検出されるたびに上記の2つを実行する必要があります。

13
alex

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
  1. %すべての行を選択

  2. ! runコマンド

  3. x保存して閉じる

2
Steven Penny