Linux:在有限空间上使用split

6

我在一台Linux机器上有一个非常大的文件,大约20GB,而我的电脑空间只有25GB。我想把这个文件分成大约100MB的部分。我知道有一个“split”命令,但它会保留原始文件。我没有足够的空间来保留原始文件。你有任何关于如何完成这个任务的想法吗?如果使用Node模块可以比Bash更容易地完成任务,我也可以尝试。


你是说你不能同时在磁盘上拥有原始文件和分割后的文件吗?这需要一个非常不同的过程(实际上是在分割文件时截断原始文件)。 - jfriend00
“tail”和“truncate”组合可行吗?使用“tail”生成部分并使用“truncate”缩小文件大小;在循环中重复操作。 - Sushil
你有检查过这篇文章吗:http://superuser.com/questions/617597/how-do-i-split-files-in-place-delete-original-as-new-files-are-written - ukesh upendran
2个回答

10

我的尝试:

#! /bin/bash

if [ $# -gt 2 -o $# -lt 1 -o ! -f "$1" ]; then
    echo "Usage: ${0##*/} <filename> [<split size in M>]" >&2
    exit 1 
fi

bsize=${2:-100}
bucket=$( echo $bsize '* 1024 * 1024' | bc )
size=$( stat -c '%s' "$1" )
chunks=$( echo $size / $bucket | bc )
rest=$( echo $size % $bucket | bc )
[ $rest -ne 0 ] && let chunks++

while [ $chunks -gt 0 ]; do
    let chunks--
    fn=$( printf '%s_%03d.%s' "${1%.*}" $chunks "${1##*.}" )
    skip=$(( bsize * chunks ))
    dd if="$1" of="$fn" bs=1M skip=${skip} || exit 1 
    truncate -c -s ${skip}M "$1" || exit 1 
done

上述假设使用 bash(1)stat(1)dd(1)truncate(1) 的 Linux 实现。它应该是尽可能快的,因为它使用 dd(1) 来复制初始文件的块。它还使用 bc(1) 来确保在 20GB 范围内的算术操作不会导致任何溢出。然而,该脚本仅在较小的文件上进行了测试,因此在对您的数据运行之前,请再次检查。


9

您可以在shell脚本中使用tail和truncate来就地拆分文件,同时销毁原始文件。我们向后就地拆分文件,以便可以使用truncate。以下是示例Bash脚本:

#!/bin/bash

if [ -z "$2" ]; then
   echo "Usage: insplit.sh <splitsize> <filename>"
   exit 1
fi

FILE="$2"
SPLITSIZE="$1"

FILESIZE=`stat -c '%s' $FILE`
BLOCKCOUNT=$(( (FILESIZE+SPLITSIZE-1)/SPLITSIZE ))
echo "Split count: $BLOCKCOUNT"

BLOCKCOUNT=$(($BLOCKCOUNT-1))
while [ $BLOCKCOUNT -ge 0 ]; do
  FNAME="$FILE.$BLOCKCOUNT"
  echo "writing $FNAME"
  OFFSET=$((BLOCKCOUNT * SPLITSIZE))
  BLOCKSIZE=$(( $FILESIZE - $OFFSET))
  tail -c "$BLOCKSIZE" $FILE > $FNAME
  truncate -s $OFFSET $FILE
  FILESIZE=$((FILESIZE-BLOCKSIZE))
  BLOCKCOUNT=$(( $BLOCKCOUNT-1 ))
done

我用一个随机文件确认了结果:

$ dd if=/dev/urandom of=largefile bs=512 count=1000
$ md5sum largefile
7ff913b62ef572265661a85f06417746  largefile
$ ./insplit.sh 200000 largefile
Split count: 3
writing largefile.2
writing largefile.1
writing largefile.0
$ cat largefile.0 largefile.1 largefile.2 | md5sum
7ff913b62ef572265661a85f06417746  -

1
两种解决方案都能起作用。但我只能接受一个答案。我已经给你点赞了。感谢你花时间回答问题,这真的帮了我很多。 - Light

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接