Question

I want to make sure that I delete required files. I have code something like

dir="/some/path/"
file = "somefile.txt"
cmd_rm= "rm -rf "+dir + file
os.system(cmd_rm)

The dir and file values are fetched from a database. How can I make sure I never end up running rm -rf /?

What things should I check before doing rm -rf?

Was it helpful?

Solution

Don't use the -r switch if you just want to remove a single file. Also, there could be spaces in the file name.

Better use the functions in Python's os module instead:

dirname = "/some/path/"
filename = "somefile.txt"
pathname = os.path.abspath(os.path.join(dirname, filename))
if pathname.startswith(dirname):
   os.remove(pathname)

Normalizing the path with abspath and comparing it against the target directory avoids file names like "../../../etc/passwd" or similar.

OTHER TIPS

You might consider using os.remove() instead since it's a great deal less dangerous than what you're attempting.

First, I suggest you to use the os.remove() and os.rmdir() functions for working with things like that. You will end up with more portable code and less headache for checking command return.

To check what you are effectively attempting to remove (you may not want to just check "/"), you can use some regular expressions on the generated path or just add a base path to all path returned from you database (depending what you are doing ...).

There is a module called shutil that provides shell-like file manipulation. If you want to delete a directory and all files and directories in it then use shutil.rmtree.

However it is implemented in python so if you are deleting a huge number of files then spawning rm may be faster, but will fail if the path has a space in it.

Use shutil.rmtree as Dave Kirby says. If you want to delete the just the file use:

dir = "/some/path/" 
file = "somefile.txt" 
cmd = os.path.join(dir, file) 
shutil.rmtree(cmd) 

If you want to delete the directory use:

dir = "/some/path/" 
file = "somefile.txt"  
shutil.rmtree(dir) 

If the files are write protected make sure you have write permissions before you run this.

Assuming that your mentioning rm -rf is not just at random, but is exactly the command you need, why not just to call it? There is a lib allowing a greater integration with shell called sh.

from sh import rm

path_to_delete = '/some/path'
if os.path.exists(path_to_delete):
    rm('-rf', path_to_delete)

PS Make sure you are not root and/or ask for user input to be extra cautious. And, yes, smoke the man to avoid deleting a single file recursively ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top