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.
-
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 08 '22 at 14:46
4 Answers
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.
- 15,925
-
1Thanks. "find /path/to/directory -maxdepth 1 -type l -delete" did the trick. – Nuno Fonseca Aug 08 '22 at 08:44
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
- 46,324
- 5
- 88
- 152
-
2With the first interactive option, you may also want to use
-depthto ensure depth-first traversal - that is, that it asks aboutroot/symlink1/symlink2beforeroot/symlink1. – minnmass Aug 08 '22 at 03:24 -
1@minnmass: But
findwon't follow symlinks by default, so it won't findroot/symlink1/symlink2- it'll findroot/symlink1, but not try to look for things under it (even if it's a link to a directory). – psmears Aug 08 '22 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 08 '22 at 13:42
-
Was going to comment exactly this but not quite as complete... beat me to it – dolt Aug 09 '22 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 09 '22 at 19:29
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
- 702
- 6
- 9
-
2Nice :-) … probably a dry-run with
echofirst before usingrmmight be a good idea to be on the safe side. – Raffa Aug 08 '22 at 15:47
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.
- 32,237
-
1
-
@PabloBianchi Yep, … only a bit though :-) … But, can be compacted more if the command grouping constructs
{}are used with theforloop … https://askubuntu.com/a/1419265 – Raffa Aug 08 '22 at 16:14