删除文件的前n个字节

删除文件的前n个字节

我遇到了一个极端的问题,我能想到的所有解决方案都很复杂。根据我的 UNIX/Linux 经验必须是一个简单的方法。

我想删除 .txt 文件中每个文件的前 31 个字节/foo/。每个文件足够长。好吧,我确信有人会给我一个我无法想象的非常简单的解决方案。也许 awk ?

答案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 指定“-c +32”而不是“+32c”,但 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/并为每个找到的执行上面的两个文件$file

答案3

tail -c +32输出其输入减去前 31 个字节。 (是的,参数相差一。)要就地编辑文件,使用海绵在循环中,或者如果您没有它并且不想打扰,请在 shell 中完成它的工作:

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

如果文件非常大(例如,大到足以拥有两个副本,甚至一个副本都是问题),您可以使用该线程中提到的技术之一

答案4

使用dd块大小 1 的速度非常慢。可以使用较大的块大小,同时指定以字节为单位的跳过,如下所示:

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

相关内容