简体   繁体   English

为什么 tar 在使用 * 通配符时通过 Python 的 subprocess.call 调用时无法创建存档?

[英]Why does tar fail to create an archive when called via Python's subprocess.call while using a * wildcard?

I'm writing a python script that should extract some data from within the existing files and then pack the original files into several tarballs.我正在编写一个 python 脚本,它应该从现有文件中提取一些数据,然后将原始文件打包成几个 tarball。 The filename format looks like this:文件名格式如下所示:

system_yymmddT0000.zip

where system can be one of several names and YYMMDDThhmm is a date and time of creation.其中system可以是多个名称之一, YYMMDDThhmm是创建日期和时间。

To make this work, I'm using tar through Python's subprocess.call so, for files starting with date 1704 like SAP_1704T0000.zip , the command is:为了使这项工作,我使用焦油通过Python的subprocess.call所以,对于开始日期1704文件一样SAP_1704T0000.zip ,命令是:

subprocess.call(["tar", "-cvf", "SAP_2017_04.tar", "SAP_1704*", "1>", "SAP_2017_04.filelist"])

However, when I run this script, I get the following error:但是,当我运行此脚本时,出现以下错误:

tar: SAP_1704*: Cannot stat: No such file or directory
tar: 1>: Cannot stat: No such file or directory
tar: SAP_2017_04.filelist: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

I also tried to pack all the arguments together like this:我还尝试将所有参数打包在一起,如下所示:

subprocess.call(["tar", "-cvf SAP_2017_04.tar SAP_1704* 1> SAP_2017_04.filelist"]) (no commas between arguments). subprocess.call(["tar", "-cvf SAP_2017_04.tar SAP_1704* 1> SAP_2017_04.filelist"]) (参数之间没有逗号)。 However, then I got the following error:但是,然后我收到以下错误:

tar: Cowardly refusing to create an empty archive
Try `tar --help' or `tar --usage' for more information.

I can't figure out what I'm doing wrong, since manually navigating inside the folder and running the command tar cvf SAP_2017_04.tar SAP_1704* 1> SAP_2017_04.filelist works just fine.我不知道我做错了什么,因为在文件夹内手动导航并运行命令tar cvf SAP_2017_04.tar SAP_1704* 1> SAP_2017_04.filelist工作得很好。

Wildcards aren't processed by tar , they need to be processed by the program that calls it.通配符不由tar处理,它们需要由调用它的程序处理。 Usually , that program is a shell.通常,该程序是一个外壳程序。

However, it doesn't have to be;然而,它不一定是; you can get much safer operation (if any of your parameters are user-configurable) by doing the work in native Python instead of using shell=True :通过在本机 Python 中完成工作而不是使用shell=True ,您可以获得更安全的操作(如果您的任何参数是用户可配置的):

subprocess.call(['tar', '-cvf', 'SAP_2017_04.tar'] + glob.glob('SAP_1704*'),
                stdout=open('SAP_2017_04.filelist', 'w'))
  • Instead of 1>somefile (an instruction to your shell to redirect stdout, FD 1, to write to somefile ), we use stdout=open('somefile', 'w') to tell Python the same thing.取而代之的1>somefile你的shell中的重定向标准输出,FD 1,指令写入somefile ),我们使用stdout=open('somefile', 'w')来告诉Python同样的事情。
  • Instead of just putting SAP_1704* directly in the command line, we call glob.glob('SAP_1704*') in Python, and add the list it returns to the argument list.我们不是直接将SAP_1704*放在命令行中,而是在 Python 中调用glob.glob('SAP_1704*') ,并将它返回的列表添加到参数列表中。

Never mind, figured it out myself (at least I think so).没关系,自己想出来的(至少我是这么认为的)。 It works like this:它是这样工作的:

substring = r"tar, -cvf SAP_2017_04.tar SAP_1704* 1> SAP_2017_04.filelist"
subprocess.call(substring, shell=True)

It seems there were two problems - escaping some special characters and also attempting to pass a list of arguments to the subprocess.call while it should be passed as a single string when using shell=True .似乎有两个问题 - 转义一些特殊字符并尝试将参数列表传递给subprocess.call而在使用shell=True时它应该作为单个字符串传递。

Big thanks to @CMMCD @BoarGules and @ErHarshRathore for putting me on the right track!非常感谢@CMMCD @BoarGules 和@ErHarshRathore 让我走上正轨!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM