3

I'm trying to remove all files in a folder /myfolder/name with spaces/files/ that have an extension like *.pyc, but leave other files in the same folder untouched.

I tried running:

$ rm  "/myfolder/name with spaces/files/*.pyc"

but I get a "No such file or directory" error.

I also tried running:

$ rm "/myfolder/name with spaces/files"*.pyc

but this seems to fail if there are no files with the *.pyc extension in the folder (it works when there are *.pyc files present).

Escaping the spaces doesn't seem to work either.

What would be the best way to do this (assuming I can't rename the path)?


EDIT: I found a solution, and I have a follow-up question:

I just found that running the below command works, with some inspiration from this similar post:

$ find "myfolder/name with spaces/files/" -name *.pyc -exec rm '{}' ';'

Is there a way to do the same as above with solely rm? Is the above command the best way to do this? My understanding is that in general -exec should be used carefully.


EDIT 2: A better solution!

Some better context: I'm trying to run these commands remotely using Fabric.

I didn't realize there was a cd context manager, but using that I found a solution:

from fabric.api import cd
with cd('/myfolder/name with spaces/files/'):
    sudo('rm -f *.pyc')

I also discovered a separate issue: using rm *.pyc caused Fabric to fail because there were no *.pyc files in the directory, so using rm -f *.pyc allowed the command to fail silently and allow Fabric to continue.

Community
  • 1
  • 1
GSTurtle
  • 101
  • 1
  • 8
  • If you can cd into the directory first you could use rm *.pyc. – Coenwulf Feb 23 '15 at 23:20
  • Thanks! I was trying to run this command remotely using [Fabric](http://www.fabfile.org/), and didn't realize Fabric has a `cd` context manager. – GSTurtle Feb 23 '15 at 23:29
  • Incidentally, the issues you're having here (where you _can't_ quote only part of a command from your Python code, whereas this would do exactly what you want in shell) illustrate why this kind of Python wrapper for shell syntax reduces expressiveness, and is otherwise a horrid idea. – Charles Duffy Feb 23 '15 at 23:41
  • 1
    Also, the `find` command you suggest is buggy. To be correct, it would need to be `find "myfolder/name with spaces/files/" -name '*.pyc' -exec rm '{}' ';'`, not `find "myfolder/name with spaces/files/" -name *.pyc -exec rm '{}' ';'`. If you don't quote the `*.pyc`, then that's expanded by the shell before `find` is started if any `.pyc` files exist in the directory from which the command is invoked. – Charles Duffy Feb 23 '15 at 23:42
  • Why don't you add the Fabric-centric solutions as answers? (Answering your own question on StackOverflow is totally legitimate, but should be done by clicking the "add answer" button, not by editing the question text; this also lets people upvote your answers and give you reputation points!). – Charles Duffy Feb 23 '15 at 23:43
  • Thanks for the helpful comments! So the command would end up deleting *.pyc files in both the target directory as well as the directory `find` was executed from? I'm pretty new to the side, I'll add it to the Answers section! – GSTurtle Feb 23 '15 at 23:47
  • Exactly what it would do depends on how many matches there were in the local directory and how they were named. If there was only one, say named `__init__.pyc`, then your `find` command would become `find ... -name __init__.pyc -exec rm {} ;`, deleting only files with that exact name; if there were more than one, it might become something like `find ... -name __init__.pyc hello.pyc world.pyc -exec rm {} ;`, which would typically result in `find` failing with an error. – Charles Duffy Feb 23 '15 at 23:49

2 Answers2

7

Found a solution, edited in the answer to the question above as 'EDIT 2'

I didn't realize there was a cd context manager in Fabric, so using that I found a solution:

from fabric.api import cd
with cd('/myfolder/name with spaces/files/'):
    sudo('rm -f *.pyc')

I also discovered a separate issue: using rm *.pyc caused Fabric to fail because there were no *.pyc files in the directory, so using rm -f *.pyc allowed the command to fail silently and allow Fabric to continue.

GSTurtle
  • 101
  • 1
  • 8
0

To do it with just rm instead of find (which is a perfectly fine way of doing it) you can just escape the spaces in the directory name:

rm /myfolder/name\ with\ spaces/files/*.pyc
beresfordt
  • 5,088
  • 10
  • 35
  • 43
  • I should have provided better context - I added an edit noting that I'm trying to run these commands with [Fabric](http://www.fabfile.org/), and escaping the spaces in the Fabric command doesn't work. – GSTurtle Feb 23 '15 at 23:36
  • 1
    In the same vein, one can `rm "/myfolder/name with spaces/files"/*.pyc`, quoting the part of the string with spaces (or any expansion that may contain spaces), but not the part with the wildcard. – Charles Duffy Feb 23 '15 at 23:46