Using Python to execute a command on every file in a folder
Asked Answered
C

7

87

I'm trying to create a Python script that would :

  1. Look into the folder "/input"
  2. For each video in that folder, run a mencoder command (to transcode them to something playable on my phone)
  3. Once mencoder has finished his run, delete the original video.

That doesn't seem too hard, but I suck at python :)

Any ideas on what the script should look like ?

Bonus question : Should I use

os.system

or

subprocess.call

?

Subprocess.call seems to allow for a more readable script, since I can write the command like this :

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

EDIT : Ok, that works :

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

I've removed the mencoder command, for clarity and because I'm still working on it.

Thanks to everyone for your input.

Chitarrone answered 13/7, 2009 at 16:50 Comment(1)
You'll need double quotes around the file path if there are spaces in it.Unstained
T
160

To find all the filenames use os.listdir().

Then you loop over the filenames. Like so:

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

If you prefer subprocess, use subprocess. :-)

Tarver answered 13/7, 2009 at 16:55 Comment(4)
This will get you subdirectory names as well as files, and won't recurse into subdirectories. This may be what Manu actually needs, but it won't be that simple if you don't want it to go wrong on subdirectories.Correy
Well the input folder should only contain video files, no subdirectoriesChitarrone
@Maciej: It's dead easy to filter on extension. There is a glob that can be used as well. import glob; glob.glob('/tmp/*.py')Tarver
What if files have similar names but in different folders?Junkman
C
34

Use os.walk to iterate recursively over directory content:

import os

root_dir = '.'

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

No real difference between os.system and subprocess.call here - unless you have to deal with strangely named files (filenames including spaces, quotation marks and so on). If this is the case, subprocess.call is definitely better, because you don't need to do any shell-quoting on file names. os.system is better when you need to accept any valid shell command, e.g. received from user in the configuration file.

Correy answered 13/7, 2009 at 17:1 Comment(1)
a bit newbe to python: are the variable names "directories, subdirectories, files" predefined words or are they similar to "self" so that I define them, but this is the convention? And what happens if I give only two or one?Riel
W
14

The new recommend way in Python3 is to use pathlib:

from pathlib import Path

mydir = Path("path/to/my/dir")
for file in mydir.glob('*.mp4'):
    print(file.name)
    # do your stuff

Instead of *.mp4 you can use any filter, even a recursive one like **/*.mp4. If you want to use more than one extension, you can simply iterate all with * or **/* (recursive) and check every file's extension with file.name.endswith(('.mp4', '.webp', '.avi', '.wmv', '.mov'))

Winglet answered 20/2, 2021 at 22:20 Comment(0)
F
8

Python might be overkill for this.

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

The rm -f "$file" deletes the files.

Fluff answered 13/7, 2009 at 18:58 Comment(2)
>> Python might be overkil defintely notBirdie
First, OP asked for Python not Bash, second, if you're going to post an answer you should probably make sure it doesn't pass on any bad habits as mentioned by @Aleks-DanielJakimenko-A.Panarabism
Q
3

AVI to MPG (pick your extensions):

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
Quid answered 13/7, 2009 at 17:8 Comment(3)
In line 5, I think you meant sourceVideo[:-4]Correy
sourceVideo contains only basename of a path.Ximenez
If mencoder needs to run in the work directory, add os.chdir('/input')Quid
G
1

Or you could use the os.path.walk function, which does more work for you than just os.walk:

A stupid example:

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)
Gametophore answered 13/7, 2009 at 18:24 Comment(1)
os.path.walk is deprecated in favour of os.walk now.Correy
A
1

I had a similar problem, with a lot of help from the web and this post I made a small application, my target is VCD and SVCD and I don't delete the source but I reckon it will be fairly easy to adapt to your own needs.

It can convert 1 video and cut it or can convert all videos in a folder, rename them and put them in a subfolder /VCD

I also add a small interface, hope someone else find it useful!

I put the code and file in here btw: http://tequilaphp.wordpress.com/2010/08/27/learning-python-making-a-svcd-gui/

Anthracosis answered 27/8, 2010 at 11:53 Comment(1)
There is a lot of code in that blog that doesn't pertain to the question. It might be helpful if you pull out the relevant code and paste it in the answer. Also, if the blog ever changes or goes down, then this answer would become of no value, while if the code was in the answer, it would always remain a valid answer.Infusionism

© 2022 - 2024 — McMap. All rights reserved.