如何使用Python将单个文件拆分为多个不同大小的文件

时间:2017-04-17 16:01:57

标签: python shell esxi

我编写了一个python脚本,它从列表中读取文件偏移量和文件名,并将一个大文件分成多个文件。对于拆分,我使用shell脚本,它将这些名称和偏移量作为输入,并使用head命令创建多个输出文件。我正在使用python将输入发送到shell脚本。这在我的Windows 7和其他Linux系统中运行良好。但是,当我尝试在ESX 6.5虚拟机管理程序上使用相同的内容时,我意识到我无法在ESX 6.5中使用相同的shell脚本,因为head命令无法正常工作,因为它在其他操作系统中工作。

list = ['IdleChk_1_E1.txt','749','IdleChk_2_E1.txt','749','reg_fifo_E1.txt','5922','igu_fifo_E1.txt','161','protection_override_E1.txt ','1904','fw_asserts_E1.txt','708','McpTrace.txt','15578','phy_dump.txt','129','GrcDumpE1.bin','3629656']

偶数元素是文件名,奇数元素是大小。

以下是我用来向shell脚本发送输入的命令:

Process_three=subprocess.Popen("./read.sh %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s" \
                             %(''.join(map(str, list_info[1:2])), ''.join(map(str, list_info[0:1])),\
                               ''.join(map(str, list_info[3:4])), ''.join(map(str, list_info[2:3])),\
                               ''.join(map(str, list_info[5:6])), ''.join(map(str, list_info[4:5])),\
                               ''.join(map(str, list_info[7:8])), ''.join(map(str, list_info[6:7])),\
                               ''.join(map(str, list_info[9:10])), ''.join(map(str, list_info[8:9])),\
                               ''.join(map(str, list_info[11:12])), ''.join(map(str, list_info[10:11])),\
                               ''.join(map(str, list_info[13:14])), ''.join(map(str, list_info[12:13])),\
                               ''.join(map(str, list_info[15:16])), ''.join(map(str, list_info[14:15])),\
                               ''.join(map(str, list_info[17:18])), ''.join(map(str, list_info[16:17])),\
                               file_name), stdout=subprocess.PIPE, shell=True)
(temp, error) = Process_three.communicate()

这是我的shell脚本。

if [ "$#" -eq 19 ];
then
{
    head -c $1 > $2
    head -c $3 > $4
    head -c $5 > $6
    head -c $7 > $8
    head -c $9 > ${10}
    head -c ${11} > ${12}
    head -c ${13} > ${14}
    head -c ${15} > ${16}
    head -c ${17} > ${18}
} < ${19}
fi

在ESX中,只有第一个头命令输出正在运行。

是否有另一种分割文件的方法。我知道有split命令但是这个命令将文件分成两个相等的一半。我需要动态大小的文件。 我希望我能从python本身分裂。顺便说一下,我是Python的新手。

2 个答案:

答案 0 :(得分:0)

从您尝试的解决方案中可以明显看出您是Python新手,但实际上您在使用subprocess库方面取得了相当惊人的进展,所以我相信您会发现自己会随着时间的推移做得更好。通常问题看起来很困难,因为您根本不了解可用工具的所有可用功能。在这种情况下,您似乎正在使用head,因为您知道可以强制执行您想要的操作,但我相信您会同意这不是一个舒适的解决方案。

处理任何需要19个参数的过程很困难 - 命令变得难以理解,并且在编写错误时更容易出错。数据驱动的方法,您在文本文件中描述您希望如何拆分文件,可能更容易处理。然后,您可以编写一个程序来读取该描述并使用它来分割文件。由于Python可以非常容易地读写文件,因此您应该发现根本不需要使用shell脚本,这将使您的解决方案更加便携。

如果我已正确理解您的shell脚本,则每个head命令从第19个(!)参数中指定的文件中获取一定数量的字节,并将它们写入指定的文件。因此,您可以使用包含表单行

的数据文件布局
N filename

其中N是允许我测试的行数我在task_description.txt创建了以下文件。

10 file1.txt
20 file2.txt
30 file3.txt

就像你的程序一样(如果我说得对),在指定的60之后的任何字节都将被忽略。所以现在我可以编写一个程序so15.py来读取任务描述并处理一些数据文件,在第一个命令行参数中命名,相应地:

import sys
in_file = sys.argv[1]
with open("task_description.txt") as td, open(in_file, "rb") as inf:
    for line in td:
        n, file_name = line.split()
        with open(file_name, "wb") as out_file:
            out_file.write(inf.read(int(n)))
        print("Wrote", n, "bytes to", file_name)

然后我使用一个包含60多个字节的数据文件来运行它 - 来自Python发行版的Misc/NEWS文件 - 使用命令

python so15.py /Users/sholden/Projects/Python/cpython/Misc/NEWS

它给出了输出

Wrote 10 bytes to file1.txt
Wrote 20 bytes to file2.txt
Wrote 30 bytes to file3.txt

作为检查,我然后运行命令

wc -l file*.txt

具有以下结果

   0       1      10 file1.txt
   2       4      20 file2.txt
   2       6      30 file3.txt
   4      11      60 total

希望你能够很容易地适应这个问题来解决你的问题。

答案 1 :(得分:0)

首先,我建议将列表转换为2元组列表,并使用整数表示数字而不是字符串。使用它更容易。我使用的是列表而不是dict,因为列表中有订单,而字典却没有。

fragments = [('IdleChk_1_E1.txt', 749), 
             ('IdleChk_2_E1.txt', 749),
             ('reg_fifo_E1.txt', 5922),
             ('igu_fifo_E1.txt', 161),
             ('protection_override_E1.txt', 1904),
             ('fw_asserts_E1.txt', 708),
             ('McpTrace.txt', 15578),
             ('phy_dump.txt', 129),
             ('GrcDumpE1.bin', 3629656)]

然后我们以二进制模式打开文件(我在这里使用Python 3),读取所需的数据量并将其写入输出文件。

with open('inputfile', 'rb') as inf:
    for fn, count in fragments:
        with open(fn, 'wb') as outf:
            outf.write(inf.read(count))

检查所有片段大小的总和不大于文件大小是个好主意。或者您可以使用-1作为最后一个片段的大小,这将使read获取所有剩余数据。