下面的代码应该给我一个“正在工作的bash脚本”
box_category=GET_COMBOBOX_value(self,self.combobox_category2,False)
list_path=Data_Location+"/program-data/programs_to_install.csv"
list=csv.reader(open(list_path),delimiter='|')
bash_file=path+"/install_programs"
if os.path.exists(bash_file):
os.remove(bash_file)
with open(bash_file, "ab") as f:
bash_list=csv.writer(f,delimiter='|')
bash_list.writerow(["#!/bin/bash"])
bash_list.writerow([" "])
string="if [ \"$(id -u)\" != \"0\" ]; then echo \"You need root permission for installing programs.\" 1>&2; exit 1; fi"
print string
bash_list.writerow([string])
for row in list :
bash_list.writerow(["apt-get --yes install "+row[0]])
time.sleep(0.2)
os.system("chmod a+x '"+bash_file+"'")首先,它“几乎”正确地生成了这个bash文件:
#!/bin/bash
"if [ ""$(id -u)"" != ""0"" ]; then echo ""You need root permission for installing programs."" 1>&2; exit 1; fi"
apt-get --yes install 0ad
apt-get --yes install audacity
apt-get --yes install banshee
apt-get --yes install barrage
..etc..但是:
bash: ./install_programs: /bin/bash^M: bad interpreter: No such file or directory。如果我删除所有内容直到第一个apt-get ..行,并添加bash扩展".sh“,解释器就会识别它。
"if [ \"$(id -u)\" != \"0\" ]; then echo \"You need root permission for installing programs.\" 1>&2; exit 1; fi"
它应写明:
if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi
我得到了这样的输出:
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package 0ad
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package audacity
Reading package lists... Done
Building dependency tree
Reading state information... Done发布于 2014-07-22 23:58:01
CSV的全部要点是用于逗号分隔的值,即每行上有多个列,用逗号分隔。这意味着,如果您的值中有一个逗号,则必须引用该值(或转义)。这些引用规则意味着,如果您的值中有一个引号字符,则必须引用该值来处理这个问题。所以,代替这个:
if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi…你最后的下场是:
"if [ ""$(id -u)"" != ""0"" ]; then echo ""You need root permission for installing programs."" 1>&2; exit 1; fi"这当然不是一个有效的bash命令。
简单的解决方案是不使用csv模块;只需将行写到文件中,而不是试图将每个行转换为csv模块编写的一个列的列表,希望得到您想要的行。
with open(bash_file, "a") as f:
f.write("#!/bin/bash\n")
f.write(" \n")
string="if [ \"$(id -u)\" != \"0\" ]; then echo \"You need root permission for installing programs.\" 1>&2; exit 1; fi"
print string
f.write(string + "\n")
for row in list:
f.write("apt-get --yes install " + row[0] + "\n")如果您厌倦了所有这些显式换行符的输入,可以将write函数包装起来:
def writeline(f, line):
f.write(line + '\n')然后,无论你做什么,
f.write(string + "\n")…您可以这样做:
writeline(f, string)这可能是个好主意;否则,您将忘记一行中的"\n“--或者更糟糕的是,错误地键入它--并花费一个小时来调试您的代码,不管您盯着它看了多少,但仍然无法运行…。
此错误:
bash: ./install_programs: /bin/bash^M: bad interpreter: No such file or directory…也是由使用csv模块造成的。
默认的CSV方言使用Windows风格的换行符,即每一行以'\r\n'结尾。(请参阅文档中的Dialect.lineterminator。)但是bash需要Unix风格的换行符,也就是说,每一行都以'\n'结尾。因此,它将额外的'\r'视为实际行的一部分。因此,在shebang行上,它不认为需要'/bin/bash'作为解释器,而是认为'/bin/bash\r'-which是一个完全有效的文件名,但是没有这个名称的文件。
你的最后一个问题很可能就是同样的问题。一个额外的不可见的'\r'字符可能会阻止fi\r匹配if,或者导致您尝试安装一个名为'0ad\r'的包,而不是'0ad'等等。
几个边注:
list;它隐藏了您可能想要使用的同名的内置类型/函数。而且,尽管出现的次数较少,但string是stdlib模块的名称,因此通常也要避免这种情况。"""if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi"""发布于 2014-07-23 00:03:01
第一条线索可能在"^M"中。这是一个回车,并且被shebang执行机制视为可执行路径的一部分。不要在其他环境中使用在Windows中创建的文本文件,除非进行适当的清理。您可以通过使用sh来运行脚本来克服这一点。正如@abarnert在他/她的回答中指出的那样,csv模块并不是输出所必需的,而且确实阻碍了它的实现。
https://stackoverflow.com/questions/24899693
复制相似问题