1

I need to remove all the files in a directory except for one file and one folder. Up to the grep I can output the correct list of items I want to remove but when i add xags, nothing is deleted.

this is the command I'm using.

ls domain.com/wp-content/themes | grep -v -E 'twentyeleven|index.php'  | xargs rm -rf
3
  • Thank you but that thread does not do exactly as I need, or at least does not go in detail on how to : keep multiple files, keep both files and directories, specify a directory path.
    – Sebastien
    Oct 5, 2011 at 7:41
  • For multiple files, maybe this: shopt -s extglob; rm !(twentyeleven|index\.php) Oct 5, 2011 at 8:17

2 Answers 2

0

you could solve this with some more diagnosis,

the command does work in practice, on a simple example.

So all you have to do is a bit of troubleshooting.

It looks like you have done troubleshooting to the point of finding ls domain.com/wp-content/themes | grep -v -E 'twentyeleven|index.php'
looks good.

Try ls file1 file2 file3 from within that directory. | rm -rf

Try echo file1 file2 file3 | rm -rf

Try another directory, maybe there's some issue with that. Basic troubleshooting will take you much further possibly to the solution.

Here is an example that works. Tested in cygwin.

user@iar ~/aa
$ ls | grep -v -E "op"
er
qw
ty
ui

user@iar ~/aa
$ ls | grep -v -E "op" | xargs rm -rf

user@iar ~/aa
$ ls
op

user@iar ~/aa
$
0

First of all, you want to use ls -1 (number 1, not lowercase L) if you want to use grep on it's output.

But the main problem is, that you list the contents of a subdirectory, but the rm command is executed in the current directory.

For example see this directory tree (. and .. entries omitted)

 a/
 a/x
 a/y
 a/z

Let's say you want to remove all from directory a except file y and use the command as you tried:

 $ ls -1 a | grep -v 'y'  | xargs rm -rf

ls -1 a gives:

 x
 y
 z

grep filters out the line with y:

 x
 z

so xargs excutes the following command:

 rm x z

But it executes the command in the top-level directory and sees only directory a, not the files x and z.

In order to make it work, you need the path of the files - easily achieved by applying a minor change to the ls command. Also we refine the grep pattern a bit:

 ls -1d a/* | grep -v '/y$'  | xargs rm -rf

So this time ls produces the following output:

 a/x
 a/y
 a/z

and the final command executed would be rm -rf a/x a/z

So now let's go back to your command line and apply the discussed changes:

 $ ls -1d domain.com/wp-content/themes/* | grep -v -E '/twentyeleven$|/index.php$'  | xargs rm -rf

One last note: Using xargs rm -rf is always venturesome (although sometimes neccessary) - be sure to check the output of the grep command first!

5
  • interesting.. though regarding the need to do -1, and I see -1 makes sense if | grep, but it works without it too. If I do $ls<ENTER> it lists 5 files: er op qw ty ui It lists them on one line. And if I do $ls | od -c I actually see \n in between each of them. Infact ls -1 | od -c looks like it dumps the same output as ls | od -c Just the \n is interpreted as new line in the case of ls -1 , but \n is still there with ls without -1.
    – barlop
    Oct 5, 2011 at 14:11
  • @barlop: But one should not assume that this is true in every environment - whereas 'ls -1' is a standard option with a standard outcome (one file per line).
    – ktf
    Oct 5, 2011 at 14:39
  • well, maybe ls including \n is standard on all *nix systems, I don't know, and if it is, then -1 is completely unnecessary! I see a thing worth noting about your method, is with globbing which you've used, it introduces something which isn't standard, some systems may be set to include . and .. (dot and dotdot) some may not, which I suppose then get expanded like (dotdot colon) ..: then the files there. And if (dotdot).. were to go literally to rm -rf , I guess it wouldn't but if it did then it's dangerous and not very portable to some systems!
    – barlop
    Oct 5, 2011 at 16:47
  • Globbing files starting with a dot would be non-standard, too ;-)
    – ktf
    Oct 6, 2011 at 8:47
  • yes i'm all for the consideration of catering to non-standard. But in the case of ls without -1, I don't know if there are *nix systems where the output doesn't have a \n. Whereas in the case of globbing, I know for example bash has an option to make globbing include . and .. that's my point, and the distinction there. Also (and i'm not relying on this, but just as a side thing) it's quite a possibility that it's default to do so in some shells 'cos I vaguely recall possibly seeing a shell script demonstrating that.
    – barlop
    Oct 6, 2011 at 11:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .