20

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, 2022 at 14:46

4 Answers 4

34

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, 2022 at 8:44
14

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, 2022 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, 2022 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, 2022 at 13:42
  • Was going to comment exactly this but not quite as complete... beat me to it 🙃
    – dolt
    Aug 9, 2022 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, 2022 at 19:29
10

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, 2022 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, 2022 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, 2022 at 16:14

You must log in to answer this question.

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