I found a lot of questions on how to delete symlinks only, or delete symlinks based on their contents, but no one has asked how to do what I want to do.
Take the following example
file-l -> ../file
file-l2 -> ../file
I want to delete file
, file-l
, and file-l2
in one fell swoop, without knowing the locations of the other files, preferably by specifying file
as an argument. (imagine that I have 100+ links to the same file in random places all over the filesystem). Primarily, I would prefer a shell script or built-in program, but external programs are also okay.
After unlink
and rm
failed to provide the desired functionality, I initially had the idea to use inodes
or stat
or something, but...
$ stat test
File: ‘test’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 811h/2065d Inode: 27001032 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ braden) Gid: ( 1000/ braden)
Access: 2015-08-30 21:30:35.578786598 -0600
Modify: 2015-08-30 21:30:35.578786598 -0600
Change: 2015-08-30 21:30:35.578786598 -0600
Birth: -
$ stat test-l
File: ‘test-l’ -> ‘test’
Size: 4 Blocks: 0 IO Block: 4096 symbolic link
Device: 811h/2065d Inode: 27001033 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ braden) Gid: ( 1000/ braden)
Access: 2015-08-30 21:30:42.074786598 -0600
Modify: 2015-08-30 21:30:41.426786598 -0600
Change: 2015-08-30 21:30:41.426786598 -0600
Birth: -
Not only does the symlink have a unique inode (that's a given) but there doesn't seem to be any information aside from the file name that I could use to conclude that "yes, this is a symlink to the file I want". If I use the filename, though, then I have to deal with regex-hell. This is something I would personally like to avoid since, in practice, the file names contain characters like space, meta-characters (?![]{}.,
), and unicode characters.
I would also like to avoid things like awk, perl, crazy hacks that exploit bugs/design-flaws in bash 4.2.XX, and other weird stuff that probably wouldn't work properly (if at all) on a fresh install of, e.g, Arch Linux or CentOS. I should basically be able to run said command/script out-of-the-box on a system that lacks awk, sed, perl, ruby, and python, and runs bash-4.1 as its shell.
If that isn't possible, then I would at least prefer the script/command use/be ubiquitous, like vi
, cat
, ls
, etc.
The bare minimum of my requirements is that the solution:
- can delete a file and all of its symlinks with only the original file as an argument
- can do so without knowing the names or locations of said symlinks
- can do so on symlinks of varying names and varying locations
- works in a fresh, minimal install of Arch Linux (or similar minimal system)
- is not a code-golf
- regexes reasonable and easy-to-understand
This is how I try to design my own scripts, so I consider it reasonable. But I nonetheless hope it isn't too demanding.
Thanks.
Edit: I feel like I'm obligated to show my work. Just requesting a script makes me feel like a jerk. So, this is what I have:
get_lnk(){
gl_file="$1"
gl_orig_a=( $(ls -l "$gl_file") )
gl_orig="${gl_orig_a[-1]}"
}
for i in *; do
get_lnk "$i"
echo "file: $gl_file"
echo "links to: $gl_orig"
echo
done
# output:
file: file-l
links to: ../file
file: file-l2
links to: ../file
This prints the name of the symlink and the name of the file it points to. This is actually the opposite of what I'm trying to do, but is reasonably useful (when all the links are in the same place).
link1 -> link2
andlink2 -> file
? I think that @Cyrus link will not find them all, but I'm not sure.