LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   How "to rm -rf *", but excluding (leaving behind) symlinks ? (https://www.linuxquestions.org/questions/linux-newbie-8/how-to-rm-rf-%2A-but-excluding-leaving-behind-symlinks-923486/)

Sabinou 01-12-2012 03:25 PM

How "to rm -rf *", but excluding (leaving behind) symlinks ?
 
Hello, it's been ages since I came here for a question, good day to everyone :)

On my server, a Debian Squeeze, I need to "empty" a domain's public_html folder, however I want to leave behind the shortcuts added by my hosting panel (virtualmin), all of them being symlinks.

In other words, I need to delete everything, except symlinks.
rm -rf * would do too much, removing the symlinks alongside the rest.

Would you know how it can be achieved ?
Thank you VERY much if you can help me, thank you ! :)

Dark_Helmet 01-12-2012 03:29 PM

Maybe this thread can be of some help: Exclude a folder from a recursive delete?

Unless you make use of the GLOBIGNORE environment variable, you will not be able to use "rm -rf *" for your command. You'll need to use a script, find, or something similar.

EDIT:
I forgot to mention, the OP in the linked thread ended up using a script that tested whether the next directory to delete was a symbolic link. That same type of test can be merged into the find command. Perhaps "! -type l"... you'll need to experiment with it before doing a full-fledged rm to make sure you get the right results.

Sabinou 01-12-2012 03:39 PM

Thank you Dark_Helmet ! :)

The globignore thing is entirely new to me (well, like so much stuff, I moved my websites to a dedi out of necessity rather than because I felt ready, haha), I'll have to dig into that.

The chown trick (suggested later in that thread) is also a great idea, and I believe it WOULD do the trick. I'm still reluctant to doing that, for "purity" reasons I'd like to keep astray from becoming root, ideally I'd like to be able to do all I need as the single user.
And there's the problem that if, some day, I have a folder with NUMEROUS symlinks instead of just 4 today, it will be an issue again and, to select all the symlinks, we'll be back to the present post.

-

To get back to business, if the "rm" command can't be used, then maybe I could search in another direction, as suggested in the first post of your linked thread.

Is there a special wildcard that can allow to select only symlinks ? Would you know, please ?
- In such a case, I could do that
mv "only symlinks" ../
rm -rf *
and then bringing the symlinks back.
- or find "only symlinks -exec and move them to another folder
- or even more simply "find all but symlinks" -exec rm -rf

All these ideas would require being able to have a special char to only pick symlinks...

MartinStrec 01-12-2012 03:57 PM

Following command delete all regular files except symlinks:

find /path/to/del -type f -exec rm -rf {} \;

I guess you needn't remove directories, it has no sense, directories can obviously contain symlinks.

For more complex of using find, see 'man find'

colucix 01-12-2012 03:58 PM

The most straightforward method could be:
Code:

find /path/to/dir ! -type l -delete
this will search for all object that are not symbolic links and will delete them recursively. Obviously the directories containing symbolic links will not be removed.

Paranoid warning: this is a very dangerous command: please re-check the path of the top search directory (or use . if it is your current working directory) and the syntax of the command line before pressing enter. You may want to run the command without -delete to check if the list of files/directories matches only the objects you want to remove.

Dark_Helmet 01-12-2012 04:01 PM

You might have missed the EDIT that I added while you were typing your response. If you're concerned about the number of symbolic links growing to an unmanageable size, then yes, GLOBIGNORE is probably not a consideration.

A (relatively) short find command will be able to handle any number of symbolic links. For example:
Code:

user@localhost$ ls -l
drwxr-xr-x 2 user user 4096 2012-01-12 15:48 another_dir
lrwxrwxrwx 1 user user  16 2012-01-12 15:48 download_link -> ../../Downloads/
drwxr-xr-x 2 user user 4096 2012-01-12 15:47 test_dir
lrwxrwxrwx 1 user user  11 2012-01-12 15:47 test_link -> ../../temp/
user@localhost$ # Display symbolic links
user@localhost$ find . -maxdepth 1 -type l
./test_link
./download_link
user@localhost$ # Display non-symbolic links
user@localhost$ find . -maxdepth 1 ! -type l
.
./test_dir
./another_dir

The problem with the non-symbolic link command is that you get the current directory reference: .
That's what half the -prune business was about in that other thread. For instance:
Code:

user@localhost$ find . -maxdepth 1 \( ! -type l \) -a \( -regex "\./.*" -print \)
./test_dir
./another_dir

With that, you can safely add the -exec portion:
Code:

user@localhost$ find . -maxdepth 1 \( ! -type l \) -a \( -regex "\./.*" \) -exec rm -R "{}" \;
And lastly, if that's too much to type, you can always create an alias for it. You just have to remember to execute it from the directory you want it to work on. You could modify the alias to work with an argument, but anyway...

EDIT:
I type too much...

EDIT2:
And I'm dumb... instead of "! -type l" the simplest substitute would be "-type d"
Code:

user@localhost$ find . -maxdepth 1 -type d -regex "\./.*" -exec rm -R "{}" \;
./test_dir
./another_dir


suicidaleggroll 01-12-2012 04:09 PM

I think Helmet's edit suggestion is what I would do. Something along the lines of:
Code:

find . ! -type l -exec rm -f {} \;
You should obviously run that without the -exec rm -f to make sure it matches what you want and doesn't match what you don't want before running the whole shebang.

Sabinou 01-13-2012 01:01 AM

(back after a good night's sleep)

Wow, these are more possibilities than I even imagined.

Mostly variations around -type l or cunningly using -type d, all them good ideas.

Thank you VERY MUCH, guys, I'm really grateful, you helped a lot ! :)


All times are GMT -5. The time now is 12:03 PM.