Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rm all files under a directory using python subprocess.call

I'm writing a script that will move files into a .trash directory in a user's home folder. I want to add the ability to empty the trash directory by calling rm -rf /home/user/.trash/* using python's subprocess.call()

~$ touch file1
~$ trash file1
['mv', 'file1', '/home/rodney/.trash/']
~$ ls .trash
file1
~$ trash --empty
['rm', '-rf', '/home/rodney/.trash/*']
~$ ls .trash
file1

As you can see the rm command did not remove the contents of the trash. However if I execute the command directly on the command line it works.

~$ rm -rf /home/rodney/.trash/*
~$ ls .trash
~$ 

The output is from the following code

print(cmd)
subprocess.call(cmd)

What is weird about this is if I exclude the * from the last argument in the cmd list then the subprocess call works but also removes the entire .trash directory. I do not want to delete the .trash directory; only everything under it.

To sum up the question

This works

import subprocess
subprocess.call(['rm', '-rf', '/home/rodney/.trash/'])

This does not

import subprocess
subprocess.call(['rm', '-rf', '/home/rodney/.trash/*'])

Why?

like image 425
rodneyxr Avatar asked Aug 13 '15 00:08

rodneyxr


People also ask

How do I run a subprocess in a specific directory?

chdir() or with the subprocess named parameter cwd which changes the working directory immediately before executing a subprocess.

Which method is used to delete a directory in Python?

remove() method in Python is used to remove or delete a file path.


2 Answers

Don't shell out.

This uses glob.glob() to identify the files to be removed, and shutil.rmtree() to remove subdirectories.

#!/usr/bin/env python
import os, os.path
import glob
import shutil

def remove_thing(path):
    if os.path.isdir(path):
        shutil.rmtree(path)
    else:
        os.remove(path)

def empty_directory(path):
    for i in glob.glob(os.path.join(path, '*')):
        remove_thing(i)

empty_directory('trash')

Example:

$ tree trash/
trash/
├── aaa
├── bbb
├── ccc
├── ddd
└── sub
    ├── iii
    └── jjj

1 directory, 6 files

$ ./go.py 

$ tree trash/
trash/

0 directories, 0 files
like image 81
Jonathon Reinhart Avatar answered Sep 17 '22 03:09

Jonathon Reinhart


Shell expand * into file names. You need to pass shell=True keyword argument so that shell will interpret *.

import subprocess
subprocess.call('rm -rf /home/rodney/.trash/*', shell=True)

According to subprocess - Frequently Used Arguments:

If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory. However, note that Python itself offers implementations of many shell-like features (in particular, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), and shutil).

like image 43
falsetru Avatar answered Sep 19 '22 03:09

falsetru