我试图使用python脚本中的shell命令打印目录中每个文件的最后一行

时间:2018-04-05 02:53:12

标签: python shell

我将文件的数量存储在变量的目录中,并将它们的名称存储在一个数组中。我无法在数组中存储文件名。 这是我写的代码片段。

{"installed":{"client_id":"698477346386-5kbs1fh3c6eu46op4qvf30ehp6md8o56.apps.googleusercontent.com","project_id":"proven-dryad-122714","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"9j4oMk4HI0ZyPvQrz0jFFA4q","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

4 个答案:

答案 0 :(得分:3)

你的shell脚本数量级太复杂了。

output = subprocess.check_output('tail -qn1 *', shell=True)

或者如果你真的喜欢,

os.system('tail -qn1 *')

然而,它不捕获Python变量中的输出。

如果你有一个最近足够的Python,你会想要使用subprocess.run()。您也可以轻松地让Python执行文件的枚举,以避免令人讨厌的shell=True

output = subprocess.check_output(['tail', '-qn1'] + os.listdir('.'))

如上所述,如果您真的只想将输出打印到屏幕而不能用于Python,那么您当然可以使用os.system(),但即使在subprocess中也是如此。 os.system()文档,因为它更通用,更高效(如果使用正确)。如果你真的坚持每个文件运行一个tail进程(也许是因为你的tail不支持-q选项?)你当然也可以这样做:

for filename in os.listdir('.'):
    os.system("tail -n 1 '%s'" % filename)

如果您的文件名包含单引号,则仍然无法正常工作。有一些解决方法,但是避免使用shell是非常受欢迎的(所以回到subprocess没有shell=True并且正确处理转义的shell元字符的问题会消失,因为没有shell可以从中转义元字符。

for filename in os.listdir('.'):
    print(subprocess.check_output(['tail', '-n1', filename]))

最后,tail并没有特别做任何Python本身无法轻易完成的事情。

for filename in os.listdir('.'):
    with open (filename, 'r') as handle:
        for line in handle:
            pass
        # print the last one only
        print(line.rstrip('\r\n'))

如果你知道预期的行长度并且文件很大,可能会seek到文件末尾附近的某个地方,但显然你需要知道距离搜索的末端有多远才能成为能够读取每个文件中的所有最后一行。

答案 1 :(得分:1)

os.system返回命令的exitcode而不是输出。尝试将subprocess.check_outputshell=True

一起使用

示例:

>>> a = subprocess.check_output("ls -l /home/demo/ | awk 'NR>1 {print $9}'", shell=True)
>>> a.decode("utf-8").split("\n")

编辑(正如@tripleee所建议的那样)你可能不想这样做,因为它会变得疯狂。 Python对这样的事情有很好的功能。例如:

>>> import glob
>>> names = glob.glob("/home/demo/*")

将直接为您提供该文件夹中的文件和文件夹列表。一旦你有了这个,你就可以len(names)来获得第一个命令。

另一种选择是:

>>> import os
>>> os.listdir("/home/demo")

在这里,glob将为您提供整个文件路径/home/demo/file.txtos.listdir将为您提供文件名file.txt

ls -l /home/demo/ | wc -l命令也不正确,因为ls -l会向您显示"总X"最重要的是提到它找到了多少文件和其他信息。

答案 2 :(得分:1)

你可能会使用一个没有太多问题的循环:

files = [f for f in os.listdir('.') if os.path.isfile(f)]

for f in files:
    with open(f, 'rb') as fh:
        last = fh.readlines()[-1].decode()
        print('file: {0}\n{1}\n'.format(f, last))
    fh.close()

<强>输出

file.txt
Hello, World!

...

如果您的文件很大,那么readlines()可能不是最佳选择。也许改为使用tail

for f in files:
    print('file: {0}'.format(f))
    subprocess.check_call(['tail', '-n', '1', f])
    print('\n')

解码是可选的,虽然对于文本“utf-8”通常有效或者如果它是二进制/文本/等的组合,那么像“iso-8859-1”这样的东西通常应该起作用。

答案 3 :(得分:0)

您无法存储文件名,因为os.system未按预期返回输出。有关详细信息,请参阅:this 来自docs

  

在Unix上,返回值是以wait()指定的格式编码的进程的退出状态。请注意,POSIX没有指定C系统()函数的返回值的含义,因此Python函数的返回值是依赖于系统的。

     

在Windows上,返回值是系统shell在运行命令后返回的值,由Windows环境变量COMSPEC给出:在command.com系统上(Windows 95,98和ME),它始终为0;在cmd.exe系统(Windows NT,2000和XP)上,这是命令运行的退出状态;在使用非本机shell的系统上,请参阅shell文档。

os.system按原样执行linux shell命令。要获取这些shell命令的输出,您必须使用python subprocess

注意:在您的情况下,您可以使用glob模块或os.listdir()获取文件名:请参阅How to list all files of a directory