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

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

私は深刻な問題に直面しており、私が考えることができる解決策はすべて複雑です。私のUNIX / Linux経験に基づいて〜しなければならない簡単な方法です。

各.txtファイルの最初の31バイトを削除したいと思います/foo/。各ファイルの長さは十分です。まあ、誰かが私が想像できない非常に簡単な解決策を提示すると確信しています。たぶんちょっと?

答え1

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

またはギルスの提案に感謝します。

for file in /foo/*
    do
      if [ -f $file ]
      then
        tail +32c $file > $file.truncated && mv $file.truncated $file
      fi
    done

注: Posix tail は "+32c" の代わりに "-c +32" を指定しますが、Solaris のデフォルト tail はそれを好みません。

   $ /usr/bin/tail -c +32 /tmp/foo > /tmp/foo1
    tail: cannot open input

/usr/xpg4/bin/tailどちらの構文も大丈夫です。

元のファイル権限を維持するには

... && mv "$file.truncated" "$file"

渡す

... && cat "$file.truncated" "$file" && rm "$file.truncated"

答え2

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

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

find以下のすべてのファイルを一覧表示し/foo/、見つかった各ファイルに対して上記の2つのファイルを実行します$file

答え3

tail -c +32入力から最初の31バイトを引いた値を出力します。 (はい、パラメータは1つずつ異なります。)ファイルをその場所で編集するには、スポンジを使用してくださいループ内またはその機能がなく、面倒にしたくない場合は、シェルでその操作を実行します。

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

ファイルが非常に大きい場合(たとえば、2つのコピーを持つのに十分な大きさ、または1つのコピーでも問題になる場合)、次のものを使用できます。このスレッドで言及された技術の1つ

答え4

ブロックサイズ1の使用はdd非常に遅いです。次のようにスキップをバイト単位で指定しながら、より大きなブロックサイズを使用できます。

dd iflag=skip_bytes if=infile.txt of=outfile.txt skip=31 bs=1M

関連情報