15

How do I remove all symlinks in a folder (dozens of them) at once? It's not practical to insert every single one of them by hand when using unlink or rm.

1
  • What do you mean by "folder"? Are you just talking about what Linux calls directories, or do you have some other usage in mind?
    – tchrist
    Aug 8 at 14:46

4 Answers 4

28

You can use the find-command to do that:

find /path/to/directory -maxdepth 1 -type l -delete

To be on the safe side, check first without the -delete-option:

find /path/to/directory -maxdepth 1 -type l

-maxdepth 1 ensures that find will look only in /path/to/directory but not in it's subfolders for symlinks. Feel free to take a look at man find.

1
  • 1
    Thanks. "find /path/to/directory -maxdepth 1 -type l -delete" did the trick. Aug 8 at 8:44
12

List the links in the current directory alias folder and check that you really want to remove them,

find -type l -ls                  # search also in subdirectories

find -maxdepth 1 -type l -ls      # search only in the directory itself

If things look good, and you want to delete these links, run

find -type l -delete              # delete also in subdirectories

find -maxdepth 1 -type l -delete  # delete only in the directory itself

If you want to delete interactively, you can use the following command line (this is safer)

find -type l -exec rm -i {} +              # delete also in subdirectories

find -maxdepth 1 -type l -exec rm -i {} +  # delete only in the directory itself
5
  • 2
    With the first interactive option, you may also want to use -depth to ensure depth-first traversal - that is, that it asks about root/symlink1/symlink2 before root/symlink1.
    – minnmass
    Aug 8 at 3:24
  • 1
    @minnmass: But find won't follow symlinks by default, so it won't find root/symlink1/symlink2 - it'll find root/symlink1, but not try to look for things under it (even if it's a link to a directory).
    – psmears
    Aug 8 at 11:02
  • @psmears: derp; I'm too used to treating symlinks to directories as just directories, and the abstraction broke. ... never mind.
    – minnmass
    Aug 8 at 13:42
  • Was going to comment exactly this but not quite as complete... beat me to it 🙃
    – dolt
    Aug 9 at 19:25
  • 1
    @minnmass 'find' by default won't search directories that are symlinks to outside the root dir. You can use -L to tell it to dereference symlinks which iirc works for directories.
    – dolt
    Aug 9 at 19:29
9

For users of the Z shell, rm *(@) will achieve this.

Zsh supports glob qualifiers that limit the type of files a glob (such as *) applies to, for example (/) for directories, (x) for executable files, (L0) for empty files, and (@) for symlinks.

For symlinks:

% ll
lrwxrwxrwx 1 test test 3 Aug  8 15:51 bar -> foo
-rw-r--r-- 1 test test 0 Aug  8 15:51 baz
-rw-r--r-- 1 test test 0 Aug  8 15:52 foo
lrwxrwxrwx 1 test test 4 Aug  8 15:51 qux -> /etc/ 

% rm *(@)                                                                         
removed 'bar'
removed 'qux'

% ll                                                                              
-rw-r--r-- 1 test test 0 Aug  8 15:51 baz
-rw-r--r-- 1 test test 0 Aug  8 15:52 foo
1
  • 2
    Nice :-) … probably a dry-run with echo first before using rm might be a good idea to be on the safe side.
    – Raffa
    Aug 8 at 15:47
7

In bash(and most shells) … The builtin command test and its variant [ has an option -h(or -L if it’s easier to remember) that will return success(exit 0) for a file if it exists and is a symbolic link … So it can be used in a shell loop like so:

for f in *
    do
    if [ -h "$f" ]
        then 
        echo rm -- "$f"
    fi
done

or a one liner like so:

for f in *; do if [ -h "$f" ]; then echo rm -- "$f"; fi done

or even more compact(bash specific … although reported to be working in zsh and ksh as well) like so:

for f in *; { [ -h "$f" ] && echo rm -- "$f"; }

Notice:

echo is there for a dry-run ... When satisfied with the output, remove echo to delete the links.

2
  • 1
    A bit more compact: [ -h "$f" ] && rm -- "$f" Aug 8 at 16:06
  • @PabloBianchi Yep, … only a bit though :-) … But, can be compacted more if the command grouping constructs {} are used with the for loop … askubuntu.com/a/1419265
    – Raffa
    Aug 8 at 16:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.