tags:

views:

206

answers:

5

How can I remove everything else in a folder except FileA, even hidden files? I use Ubuntu.

I tried the following unsuccessfully

rm [^fileA]
+5  A: 
find . -not -name fileA -exec rm {} \;

Note that this will only delete files, not folders. Believe me, you don't want to delete folders like that.

Can Berk Güder
It will also delete files in sub-folders!
Adrian Pronk
Also, if you can use "+" on the end of the -exec command instead of ";" (or "\;") your command will generally run faster. Not available in all versions of "find"
Adrian Pronk
@Adrian: that's correct.
Can Berk Güder
The incantation above will call 'rm' for every file found, instead try:"find . -not -name fileA | xargs rm" which calls rm only once with all the files as arguments
dsm
@dsm: You can do the same thing without xargs by using the "+" suffix I mentioned above. This is supported by GNU find which is used in Linux. Also, it may call rm more than once if the number of files exceeds the command-line capacity (which is very high on Linux)
Adrian Pronk
+1  A: 

You also could do it interactively,

rm -i * .*

The * is for all files (except hidden files). The .* is for all hidden files

gene@vmware:/tmp/test$ ls -al
total 8
drwxr-xr-x  2 gene    gene    4096 2009-03-11 12:51 .
drwxrwxrwt 12 root    root    4096 2009-03-11 12:51 ..
-rw-r--r--  1 gene    gene       0 2009-03-11 12:51 fileA
-rw-r--r--  1 gene    gene       0 2009-03-11 12:51 .fileB
gene@vmware:/tmp/test$ rm -i * .*
rm: remove regular empty file `fileA'? n
rm: cannot remove directory `.'
rm: cannot remove directory `..'
rm: remove regular empty file `.fileB'? y
gene@vmware:/tmp/test$ ls -al
total 8
drwxr-xr-x  2 gene    gene    4096 2009-03-11 12:51 .
drwxrwxrwt 12 root    root    4096 2009-03-11 12:51 ..
-rw-r--r--  1 gene    gene       0 2009-03-11 12:51 fileA
CoverosGene
+1  A: 

For multiple files, the following will remove all files apart from those that have FileA or FileB in the name.

for file in *
do
  if [ x`echo $file | grep -ve "\(FileA\|FileB\)"` == x ]; then
    rm $file
  fi
done

It's more useful in a long list of files. If it's only a short list, I'd go with CoverosGene's response.

Andy
Why not just: if [ "$file" = FileA -o "$file" = FileB ] ...
Adrian Pronk
I know, I'm using a steam-roller to crack nuts, but with grep's regexp it's really extensible, just in case there are more complicated situations - the above will not delete FileA, FileAA, FileAB etc because it's looking for FileA within the filename, not checking if the whole filename is FileA
Andy
+1  A: 

Most ways of doing this based on parsing the directory list are likely to be error prone.

If you have write access to the parent directory, and your necessary file is in sub-directory foo, how about:

% mkdir bar
% mv foo/fileA bar
% rm -rf foo
% mv bar foo

i.e. get your essential file(s) the hell out of the way first!

Alnitak
+3  A: 

Use extglob. Assuming that FileA is a regular file (i.e. does not begin with a .), then you can do:

shopt -s extglob  # Enable extglob
rm !(FileA) .*  # Remove all regular files not named FileA and all hidden files

If instead FileA is a hidden file, this won't work, since the !(pattern) construct only creates a list of all regular files not matching pattern.

Adam Rosenfield