1

Is there a way, I can execute in python a bash command with expansion: *

I tried thousand ways with no luck.

Actually I want to have a python script which enters each directory in the current dir, and executes a given bash command there (possibly a bash command with an expansion: *).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Adobe
  • 12,967
  • 10
  • 85
  • 126
  • 1
    possible duplicate of [Python Command line execution](http://stackoverflow.com/questions/7306178/python-command-line-execution) – Ignacio Vazquez-Abrams Mar 03 '12 at 16:19
  • Actually it's tough to tell how to solve your problem without seeing some code. – machine yearning Mar 03 '12 at 16:27
  • @IgnacioVazquez-Abrams: I don't think this qualifies as a duplicate, just because the answer is the same. We want people to be able to search for the question, not the answer, right? – machine yearning Mar 03 '12 at 17:04
  • @machine: They both ask how to use a glob with subprocess. – Ignacio Vazquez-Abrams Mar 03 '12 at 17:20
  • 1
    @Ignacio Vazquez-Abrams: if it is a duplicate then [my answer](http://stackoverflow.com/a/9547674/4279) should also answer [the question that you've linked](http://stackoverflow.com/questions/7306178/python-command-line-execution) but it is certainly not. – jfs Mar 03 '12 at 17:30

3 Answers3

3
import os
from subprocess import check_call

cmd = 'echo *' # some shell command that may have `*`
for dirname in filter(os.path.isdir, os.listdir(os.curdir)):
    check_call(cmd, shell=True, cwd=dirname)
  • filter(os.path.isdir, os.listdir(os.curdir)) lists all subdirectories of the current directory including those that starts with a dot (.)
  • shell=True executes command given as cmd string through the shell. * if present is expanded by the shell as usual
  • cwd=dirname tells that the command should be executed in dirname directory
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • It works exactly as I wanted, but why there's nothing about `cwd` arg of `check_call` at [python docs](http://docs.python.org/library/subprocess.html#subprocess.check_call). – Adobe Mar 05 '12 at 14:06
  • 1
    @Adobe: the docs explicitly mention *"The full function signature is the same as that of the [Popen constructor](http://docs.python.org/library/subprocess.html#popen-constructor) - this functions passes all supplied arguments directly through to that interface."* – jfs Mar 05 '12 at 14:54
1

Would you maybe have use for the glob module?

>>> import glob
>>> glob.glob("*")
['build', 'DLLs', 'Doc', 'ez_setup.py', 'foo-bar.py', 'include', 'Lib', 'libs','LICENSE.txt', 'NEWS.txt', 'python.exe', 'pythonw.exe', 'README.txt', 'Removesetuptools.exe', 'Scripts', 'selectitems.py', 'selectitems.pyc', 'setuptools-wininst.log', 'share', 'so_vector.py', 'tcl', 'Tools', 'w9xpopen.exe']
>>>
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • I'm aware of glob, but I wanted to give a bash command as an argument to a python script. – Adobe Mar 05 '12 at 14:01
1

Since you're going to have the shell execute the command, let the shell do the expansion of the shell metacharacters. You can run:

sh -c "your_commaand -with *"

The shell will process the globbing for you and execute the command.

That leaves you with the problem of traversing the subdirectories of the current directory. There must be a Python module to do that.

If you decide your program should chdir() to the sub-directories, you must be careful to come back to the starting directory after processing each one. Alternatively, the shell can deal with that for you, too, using:

sh -c "cd relevant-subdir; your_command -with *"

This avoids problems because the shell is a separate process switching directories without affect your main Python process.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278