[英]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_output
与shell=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.txt
而os.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.system
按os.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.