我的python脚本是以下代码:
1 import subprocess
2
3 # initial 'output' to make
4 r0 = 21
5 # number of runs to make
6 rn = 10
7
8 rf = r0+rn
9
10 for i in range(r0, rf):
11 #output directory
12 opt_dir = 'output'+str(i)
13 #put it in this output directory
14 popt_dir = './output'+str(i)
15
16 subprocess.call(['mkdir', opt_dir])
17 subprocess.call(['./exp_fit', 'efit.inp'])
18 subprocess.call(['mv', 'at*', popt_dir])
意图是:
我有一个名为“exp_fit”的程序,它接受一个输入文件“efit.inp”。一次调用./exp_fit efit.inp
将创建名为'at0_l0_l0','at0_l1_l-1',...等的输出文件(共有475个以'at'开头的文件)。
现在,我已经通过运行'exp_fit'生成数据文件,然后使用以下bash命令创建输出目录并将它们移动到输出目录中: (例如,使用我的代码的第20次运行)
mkdir output20
mv at* ./output20
所以我认为我的脚本应该做同样的事情。但是,它只执行以下操作:
(1)它正确生成所有输出文件(以'at'开头的475个文件) (2)它正确创建了所需的目录(output21 - output30) (3)但是,它并没有正确地将所有以'at'开头的输出文件移动到所需的目录中。为什么是这样?第18行的调用是否应该正确执行命令将所有以'at'开头的文件移动到所需的目录中?
我应该用bash而不是python编写这个脚本吗?这有什么问题?
答案 0 :(得分:5)
不要发出subprocess
调用您可以从Python本地执行的操作。要移动文件/目录,只需使用os.rename
。
要创建目录,请使用os.mkdir
。
要执行外部程序,使用subprocess
是正确的工具。
答案 1 :(得分:3)
问题是这个子进程命令
subprocess.call(['mv', 'at*', './output20'])
与在提示符下键入此内容不同
$ mv at* ./output20
在后一种情况下,bash glob扩展将单个at*
参数转换为mv
命令的匹配文件名的参数列表。所以内核将第二个视为
['mv', 'at0_l0_l0', 'at0_l1_l-1', './output20']
kev's answer告诉Python通过shell传递命令,因此将发生转义。
但更好的解决方案是使用glob
模块和os.rename
库,而不是调用子进程。创建子进程非常昂贵,使用shell=True
可能会导致安全漏洞,因此最好避免这种习惯。
(实际上,我建议创建输出目录,切换到它,然后从该目录中运行exp_fit
程序。然后你不必移动输出。首先尝试。)
答案 2 :(得分:1)
如果shell=True
,可执行参数指定要使用的shell
在Unix上,默认shell为/bin/sh
。
subprocess.call(['mv', 'at*', popt_dir], shell=True)