简体   繁体   English

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

[英]I am trying to print the last line of every file in a directory using shell command from python script

I am storing the number of files in a directory in a variable and storing their names in an array. 我将文件的数量存储在变量的目录中,并将其名称存储在数组中。 I'm unable to store file names in the array. 我无法在阵列中存储文件名。 Here is the piece of code I have written. 这是我编写的代码。

import os
temp = os.system('ls -l /home/demo/ | wc -l')

no_of_files = temp - 1

command = "ls -l /home/demo/ | awk 'NR>1 {print $9}'"

file_list=[os.system(command)]

for i in range(len(file_list))
    os.system('tail -1 file_list[i]')

Your shell scripting is orders of magnitude too complex. 您的Shell脚本数量级太复杂。

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

or if you really prefer, 或者,如果您真的喜欢,

os.system('tail -qn1 *')

which however does not capture the output in a Python variable. 但是,它不会在Python变量中捕获输出。

If you have a recent-enough Python, you'll want to use subprocess.run() instead. 如果您使用的是最近使用的Python,则可以改用subprocess.run() You can also easily let Python do the enumeration of the files to avoid the pesky shell=True : 您还可以轻松地让Python对文件进行枚举,以避免讨厌的shell=True

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

As noted above, if you genuinely just want the output to be printed to the screen and not be available to Python, you can of course use os.system() instead, though subprocess is recommended even in the os.system() documentation because it is much more versatile and more efficient to boot (if used correctly). 如上所述,如果您确实只希望将输出打印到屏幕上而不对Python可用,则当然可以使用os.system() ,尽管即使在os.system()文档中也建议使用subprocess os.system()因为(如果使用正确),它的通用性和启动效率更高。 If you really insist on running one tail process per file (perhaps because your tail doesn't support the -q option?) you can do that too, of course: 如果您确实坚持每个文件运行一个tail进程(也许是因为tail不支持-q选项?),您当然也可以这样做:

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

This will still work incorrectly if you have a file name which contains a single quote. 如果您的文件名包含单引号,则此方法仍将无法正常工作。 There are workarounds, but avoiding a shell is vastly preferred (so back to subprocess without shell=True and the problem of correctly coping with escaping shell metacharacters disappears because there is no shell to escape metacharacters from). 有解决方法,但是避免使用外壳程序是非常可取的(因此,返回到没有shell=True subprocess ,由于没有外壳程序可以逃脱元字符,因此正确应对转义的外壳元字符的问题就消失了)。

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

Finally, tail doesn't particularly do anything which cannot easily be done by Python itself. 最后, 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'))

If you have knowledge of the expected line lengths and the files are big, maybe seek to somewhere near the end of the file, though obviously you need to know how far from the end to seek in order to be able to read all of the last line in each of the files. 如果您知道预期的行长并且文件很大,则可以seek到文件末尾附近的某个地方,尽管显然您需要知道从末尾寻找多远才能读取所有最后一个每个文件中的一行。

os.system returns the exitcode of the command and not the output. os.system返回命令的os.system ,而不是输出。 Try using subprocess.check_output with shell=True 尝试将subprocess.check_outputshell=True

Example: 例:

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

Edit (as suggested by @tripleee) you probably don't want to do this as it will get crazy. 编辑(由@tripleee建议),您可能不想这样做,因为它会变得疯狂。 Python has great functions for things like this. Python对于此类事情具有强大的功能。 For example: 例如:

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

will directly give you a list of files and folders inside that folder. 将直接为您提供该文件夹中的文件和文件夹列表。 Once you have this, you can just do len(names) to get the first command. 一旦有了这个,就可以执行len(names)来获得第一个命令。

Another option is: 另一个选择是:

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

Here, glob will give you the whole filepath /home/demo/file.txt and os.listdir will just give you the filename file.txt 在这里,glob将为您提供整个文件路径/home/demo/file.txtos.listdir将仅为您提供文件名file.txt

The ls -l /home/demo/ | wc -l ls -l /home/demo/ | wc -l ls -l /home/demo/ | wc -l command is also not the correct value as ls -l will show you "total X" on top mentioning how many total files it found and other info. ls -l /home/demo/ | wc -l命令也不是正确的值,因为ls -l将在顶部显示“总X”,并指出找到的文件总数以及其他信息。

You could likely use a loop without much issue: 您可能会使用一个没有太多问题的循环:

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()

Output : 输出

file.txt
Hello, World!

...

If your files are large then readlines() probably isn't the best option. 如果您的文件很大,则readlines()可能不是最佳选择。 Maybe go with tail instead: 也许用tail代替:

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

The decode is optional, although for text " utf-8 " usually works or if it's a combination of binary/text/etc then maybe something such as " iso-8859-1 " usually should work. 解码是可选的,尽管对于文本“ utf-8 ”通常可以工作,或者如果它是二进制/文本/等的组合,那么诸如“ iso-8859-1 ”之类的东西通常应该可以工作。

you are not able to store file names because os.system does not return output as you expect it to be. 您无法存储文件名,因为os.system不会像您期望的那样返回输出。 For more information see : this . 有关更多信息,请参见: this
From the docs 来自文档

On Unix, the return value is the exit status of the process encoded in the format specified for wait(). 在Unix上,返回值是以为wait()指定的格式编码的进程的退出状态。 Note that POSIX does not specify the meaning of the return value of the C system() function, so the return value of the Python function is system-dependent. 请注意,POSIX没有指定C system()函数的返回值的含义,因此Python函数的返回值与系统有关。

On Windows, the return value is that returned by the system shell after running command, given by the Windows environment variable COMSPEC: on command.com systems (Windows 95, 98 and ME) this is always 0; 在Windows上,返回值是由Windows环境变量COMSPEC给出的运行命令后系统外壳返回的值:在command.com系统(Windows 95、98和ME)上,该值始终为0; on cmd.exe systems (Windows NT, 2000 and XP) this is the exit status of the command run; 在cmd.exe系统(Windows NT,2000和XP)上,这是命令运行的退出状态; on systems using a non-native shell, consult your shell documentation. 在使用非本机外壳的系统上,请查阅您的外壳文档。

os.system executes linux shell commands as it is. os.systemos.system执行linux shell命令。 for getting output for these shell commands you have to use python subprocess 为了获得这些shell命令的输出,您必须使用python subprocess

Note : In your case you can get file names using either glob module or os.listdir() : see How to list all files of a directory 注意:您可以使用glob模块或os.listdir()获得文件名:请参阅如何列出目录中的所有文件

暂无
暂无

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

相关问题 我正在尝试编写Python脚本以在目录中打印文件列表 - I am trying to write a Python Script to Print a list of Files In Directory 通过命令行在目录中的每个文件中运行 python 脚本 - run python script in every file in a directory through command line 我正在尝试使用shell命令在python中发送邮件。 但是变量不会在脚本中被替换 - I am trying to send mail in python using shell command . But variable does not get substituted in script 我正在尝试使用line.split('\\ n)->无法识别行从类似文件的目录中打印一些关键行 - I am trying to print a few key lines from a directory of like files using line.split('\n) --> not recognizing lines 我正在尝试使用 python 从 json 文件中打印信息 - I am trying to print information from a json file with python 尝试使用 python 将 shell 命令的输出写入 JSON 文件 - Trying to write output from shell command to JSON file using python 当我尝试从python运行shell'sed'命令时出现错误 - Getting error when I am trying to run shell 'sed' command from python Python:我正在尝试重命名(切掉)单个目录中文件名的最后15个字符 - Python: I am trying to rename (chop off) the last 15 characters from filenames in a single directory 在 python 中,我如何仅打印由 shell 命令产生的标准输出的第一行 - In python how can i print only the first line of stdout which results from a shell command 使用glob.glob在目录中的每个文件中搜索并打印一行 - Search and print a line in every file in directory using glob.glob
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM