I am trying to write a very simple Bash shell script that will cd in a specific directory, it will remove all files and directories except some few selected ones and then cd back to the original dir.
My code is:
#!/bin/bash
cd /path/to/desired/directory
shopt -s extglob
rm !\(filename1\|filename2\|filename3\) -rf
cd -
I have tried many different ways to write the symbols '(' and '|', with single or double quotes or backslash but nothing worked. Note, that shopt -s extglob
and rm !(filename1|filename2) -rf
work fine outside a script.
Probably I am committing a standard and fundamental bash-scripting error that I cannot see, but experience is to come...
Any suggestions!? Thanks in advance.
Two problems I can see right off the bat:
-rf
argument torm
must come before the filenames!
,(
,|
and)
should not be escaped with backslashesTry this instead:
If it's still not working, remove the
-f
argument, and you'll get error messages about what's going wrong instead of silently suppressing them. To print out the name of each file removed, you can add the-v
option as well.If you have a recent version of
find
, then use:Check the output and replace
-print
with-delete
if it prints only the files that you really want to delete.If your version of
find
doesn't support-delete
, use-type f -exec rm "{}" \;
Note that this will only delete files. This is important: If you say to keep file
x
but that file is in a foldery
, then it would ignorex
only to delete it later with the whole foldery
.To get rid of all empty folders (and this preserving the files you want to keep):
(source: How to Find and Delete Empty Directories and Files in Unix)
assuming you have files:
You could do:
ls | grep -v "nodel.\+" | xargs rm -rf
to use advanced regexp syntax to exclude files.
Explanation:
ls --- lists current directory (ls -d to list only directories)
grep -v --- v flag specifies what NOT TO MATCH + grep allows to write perl style regexp if you supply -P flag
xargs --- applies action "rm -rf" on each of the items
I don't recommend trying to write a rule to exempt specific files. What I would be more likely to do, would be to try and find either a filemask/glob, or some other anchor in the names of the files that you do want to remove, which the files you want to keep, does not have. In most cases, you could probably do that by extension. Unfortunately, because you haven't mentioned what the names of any of the files are, I can't help you more specifically.
Something like two (or more) find loops:-
If not, look for some other common characteristic of the files. If there isn't one, you might need to rename your files to give yourself one. I always put lots of anchors (seperated name fields, extensions etc) in my filenames, because that way I have a lot of different ways for doing what I need with them. My usual name format is:-
Plus signs are field seperators, dashes are for spaces, but with no dashes as either first or last characters. All lowercase letters, and no control characters or other non-alphanumerics allowed. As a result, I can cut those up with awk, cut, or whatever else I might want to use, and rename them easily. Putting the extension at the start of the name, also means that ls only needs one flag (-l) to get a perfectly ordered file system.
If you know how to use your directory structure as a database with the basic POSIX tools, you sometimes won't need to install anything more complicated, in order to do what you want.
You've got a long char limit on filenames in UNIX, as well as tab completion for navigating around long names. Don't be afraid to make liberal use of both of them.
Try below:
Good Luck!