使用Python在文件夹中的每个文件上执行命令


68

我正在尝试创建一个Python脚本,该脚本将:

  1. 查看文件夹“ / input”
  2. 对于该文件夹中的每个视频,运行一个mencoder命令(以将其转码为我的手机上可播放的内容)
  3. mencoder完成运行后,删除原始视频。

这似乎不太难,但是我很讨厌python :)

关于脚本的外观有什么想法?

奖励问题:我应该使用

操作系统

要么

subprocess.call

Subprocess.call似乎允许使用更具可读性的脚本,因为我可以这样编写命令:

cmdLine = ['mencoder',sourceVideo,'-ovc','copy','-oac','copy','-ss','00:02:54','-endpos','00:00: 54”,“-o”,destinationVideo]

编辑:好的,这可行:

import os, subprocess

bitrate = '100'
mencoder = 'C:\\Program Files\\_utilitaires\\MPlayer-1.0rc2\\mencoder.exe'
inputdir = 'C:\\Documents and Settings\\Administrator\\Desktop\\input'
outputdir = 'C:\\Documents and Settings\\Administrator\\Desktop\\output'

for fichier in os.listdir(inputdir):
    print 'fichier :' + fichier
    sourceVideo = inputdir + '\\' + fichier
    destinationVideo = outputdir + '\\' + fichier[:-4] + ".mp4"

    commande = [mencoder,
               '-of',
               'lavf',
               [...]
               '-mc',
               '0',

               sourceVideo,
               '-o',
               destinationVideo]

    subprocess.call(commande)

os.remove(sourceVideo)
raw_input('Press Enter to exit')

为了清楚起见,我删除了mencoder命令,因为我仍在处理它。

感谢大家的投入。


没问题,我仍然遇到上一个问题。“ Windows找不到指定的文件”。Python和/或Windows不喜欢文件名和文件夹名中的空格。:(
Manu

如果文件路径中有空格,则需要在文件路径两边加上双引号。
tgray

Answers:


133

要查找所有文件名,请使用 os.listdir()

然后,您遍历文件名。像这样:

import os
for filename in os.listdir('dirname'):
     callthecommandhere(blablahbla, filename, foo)

如果您喜欢子流程,请使用子流程。:-)


4
这将使您获得子目录名称以及文件,并且不会递归到子目录中。这可能是Manu实际需要的,但是如果您不希望它在子目录上出错,就不会那么简单。
Maciej Pasternacki

那么输入文件夹应该只包含视频文件,没有子目录
Manu

3
@ Maciej:很容易过滤扩展名。也可以使用一个glob。import glob; glob.glob('/tmp/*.py')
Lennart Regebro

1
您可以将glob位添加到答案中吗?这对通过文件夹进行递归搜索有效吗?os.listdir(glob2.glob('/ dirname / ** / *。mov'))中的文件名:在此处调用thecommand
user391339,2016年

1
这不是他要的,这已经是公认的答案七年了,所以不,我不会添加它。我认为它不适用于递归搜索。关于如何执行此操作,还有很多其他问题和答案。以下是glob的文档:docs.python.org/2/library/glob.html
Lennart Regebro

32

使用os.walk递归遍历目录内容:

import os

root_dir = '.'

for directory, subdirectories, files in os.walk(root_dir):
    for file in files:
        print os.path.join(directory, file)

此处的os.system和subprocess.call之间没有真正的区别-除非您必须处理名称奇怪的文件(文件名包括空格,引号等)。如果是这种情况,那么subprocess.call绝对会更好,因为您无需对文件名进行任何shell引用。当您需要接受任何有效的Shell命令(例如在配置文件中从用户那里收到的命令)时,os.system会更好。


这正是我想要的。基本上是linux命令行上的python版本的“ find。-type f”。
chrowe 2012年

python有点新:变量名是“目录,子目录,文件”的预定义词还是它们类似于“ self”,以便我定义它们,但这是惯例吗?如果我只给两个或一个会怎样?
pashute

9

Python可能对此过于杀伤。

for file in *; do mencoder -some options $file; rm -f $file ; done

2
>> Python可能不会彻底崩溃
ghostdog74

1
“当您拥有的只是一把锤子时,一切看起来都像钉子”是我的评论所针对的。
Kurt

1
请引用您的变量。也使用-。google“重击陷阱”以了解原因。
Aleks-Daniel Jakimenko-A。

1
首先,OP要求使用Python而不是Bash,其次,如果要发布答案,则可能应确保它不会传递@ Aleks-DanielJakimenko-A提到的任何不良习惯。
StarKiller4011 '18 / 12/14

3

AVIMPG(选择您的扩展程序):

files = os.listdir('/input')
for sourceVideo in files:
    if sourceVideo[-4:] != ".avi"
        continue
    destinationVideo = sourceVideo[:-4] + ".mpg"
    cmdLine = ['mencoder', sourceVideo, '-ovc', 'copy', '-oac', 'copy', '-ss',
        '00:02:54', '-endpos', '00:00:54', '-o', destinationVideo]
    output1 = Popen(cmdLine, stdout=PIPE).communicate()[0]
    print output1
    output2 = Popen(['del', sourceVideo], stdout=PIPE).communicate()[0]
    print output2

在第5行中,我认为您的意思是sourceVideo [:-4]
Maciej Pasternacki

sourceVideo仅包含路径的基本名称。
SilentGhost

如果mencoder需要在工作目录中运行,请添加os.chdir('/ input')
gimel

1

或者,您可以使用os.path.walk函数,该函数为您完成的工作不仅仅是os.walk:

一个愚蠢的例子:

def walk_func(blah_args, dirname,names):
    print ' '.join(('In ',dirname,', called with ',blah_args))
    for name in names:
        print 'Walked on ' + name

if __name__ == '__main__':
    import os.path
    directory = './'
    arguments = '[args go here]'
    os.path.walk(directory,walk_func,arguments)

2
现在不赞成使用os.path.walk,而赞成使用os.walk。
Maciej Pasternacki

1

我有一个类似的问题,在网络上有很多帮助,这篇文章我做了一个小应用程序,我的目标是VCD和SVCD,我没有删除源,但我认为适应您自己的方法很容易需要。

它可以转换1个视频并将其剪切,也可以将所有视频转换为一个文件夹,将其重命名并将其放在子文件夹/ VCD中

我还添加了一个小界面,希望其他人发现它有用!

我将代码和文件放在这里顺便说一句:http : //tequilaphp.wordpress.com/2010/08/27/learning-python-making-a-svcd-gui/


1
该博客中有很多与问题无关的代码。如果您拉出相关代码并将其粘贴到答案中,可能会有所帮助。此外,如果博客曾经更改或关闭,那么此答案将毫无价值,而如果代码在答案中,则它将始终是有效答案。
尼克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.