- Is there a way to edit a symlink without deleting it first? [duplicate]
- 10 Answers 10
- Symlink Tutorial in Linux – How to Create and Remove a Symbolic Link
- Difference Between a Soft Link and a Hard Link
- How to Create a Symlink
- How to Create a Symlink for a File – Example Command
- How to Create a Symlink for a Folder – Example Command
- How to remove a symlink
- How to Use Unlink to Remove a Symlink
- How to use rm to Remove a Symlink
- How to Find and Delete Broken Links
- Wrapping up
- Replace Symbolic Links with Files
- 16 Answers 16
Is there a way to edit a symlink without deleting it first? [duplicate]
Now I want to change the location that the symlink links to. How do I do that? is there a way to do it without deleting it first?
10 Answers 10
You could create the new link with a different name, then move it to replace the old link.
ln -s /location/to/link linkname
ln -s /location/to/link2 newlink mv newlink linkname
If newlink and linkname are on the same physical device the mv should be atomic.
FYI, i’m sure this works on some os but this didn’t work for me, the move operation just removed the ‘new’ link instead of replacing the old one. i still had to rm first.
@pstanton You mean that mv newlink linkname caused the newlink file to be deleted, but didn’t overwrite the linkname file? Did it do this silently? That seems extremely mysterious.
mv newlink linkname will move your newlink into linkname if they are directories. So this method is not 100% perfect.
Try ln -sf new_destination linkname .
This is non-atomic, though. See my answer for details. I’m not clear whether that’s the poster’s concern or not.
This also won’t work with symlinks pointing to directories. It will just create a new symlink inside the old target directory.
Just change the symlink target:
# ln -sfT /path/to/new/target linkname
This is an instant, atomic change.
-T, —no-target-directory treat LINK_NAME as a normal file always you can brew install coreutils and access the GNU versions with a g prefix, like gln if you want the GNU versions on macOS. saves a lot of headache when there are subtle differences like this.
If the symlink targets are directories, you need to add the -T flag to the mv command, otherwise it moves the new symlink in to the target directory of the old symlink.
Example of atomically switching a website to a new version:
Original setup — website is stored in www1 directory, vhost pointing at www symlink:
Browse to website, see old version.
Put new website files in new www2 directory.
Set up new symlink to new website:
Move www symlink to directory of new website:
Browse to website, see new version immediately.
So apparently the version of mv on my NAS’s microkernel doesn’t support the -T argument. Any alternative suggestions for doing this atomically?
Try creating the symlink with the -f (force) flag. That seems to work. See the answer below: ln -sf new_destination linkname
On OSX, the man page for ln says you can do it like this
ln -shf /location/to/link link name
The options are as follows:
-F If the target file already exists and is a directory, then remove it so that the link may occur. The -F option should be used with either -f or -i options. If none is specified, -f is implied. The -F option is a no-op unless -s option is specified. -h If the target_file or target_dir is a symbolic link, do not follow it. This is most useful with the -f option, to replace a symlink which may point to a directory. -f If the target file already exists, then unlink it so that the link may occur. (The -f option overrides any previous -i options.) -i Cause ln to write a prompt to standard error if the target file exists. If the response from the standard input begins with the character `y' or `Y', then unlink the target file so that the link may occur. Other- wise, do not attempt the link. (The -i option overrides any previous -f options.) -n Same as -h, for compatibility with other ln implementations. -s Create a symbolic link. -v Cause ln to be verbose, showing files as they are processed.
Symlink Tutorial in Linux – How to Create and Remove a Symbolic Link
Dillion Megida
A symlink (also called a symbolic link) is a type of file in Linux that points to another file or a folder on your computer. Symlinks are similar to shortcuts in Windows.
Some people call symlinks «soft links» – a type of link in Linux/UNIX systems – as opposed to «hard links.»
Difference Between a Soft Link and a Hard Link
Soft links are similar to shortcuts, and can point to another file or directory in any file system.
Hard links are also shortcuts for files and folders, but a hard link cannot be created for a folder or file in a different file system.
Let’s look at the steps involved in creating and removing a symlink. We’ll also see what broken links are, and how to delete them.
How to Create a Symlink
The syntax for creating a symlink is:
ln is the link command. The -s flag specifies that the link should be soft. -s can also be entered as -symbolic .
By default, ln command creates hard links. The next argument is path to the file (or folder) that you want to link. (That is, the file or folder you want to create a shortcut for.)
And the last argument is the path to link itself (the shortcut).
How to Create a Symlink for a File – Example Command
ln -s /home/james/transactions.txt trans.txt
After running this command, you will be able to access the /home/james/transactions.txt with trans.txt . Any modification to trans.txt will also be reflected in the original file.
Note that this command above would create the link file trans.txt in your current directory. You can as well create a linked file in a folder link this:
ln -s /home/james/transactions.txt my-stuffs/trans.txt
There must be a directory already called «my-stuffs» in your current directory – if not the command will throw an error.
How to Create a Symlink for a Folder – Example Command
This would create a symlinked folder called ‘james’ which would contain the contents of /home/james . Any changes to this linked folder will also affect the original folder.
How to remove a symlink
Before you’d want to remove a symlink, you may want to confirm that a file or folder is a symlink, so that you do not tamper with your files.
Running this command on your terminal will display the properties of the file. In the result, if the first character is a small letter L (‘l’), it means the file/folder is a symlink.
You’d also see an arrow (->) at the end indicating the file/folder the simlink is pointing to.
There are two methods to remove a symlink:
How to Use Unlink to Remove a Symlink
This deletes the symlink if the process is successful.
Even if the symlink is in the form of a folder, do not append ‘/’, because Linux will assume it’s a directory and unlink can’t delete directories.
How to use rm to Remove a Symlink
As we’ve seen, a symlink is just another file or folder pointing to an original file or folder. To remove that relationship, you can remove the linked file.
Note that trying to do rm james/ would result an error, because Linux will assume ‘james/’ is a directory, which would require other options like r and f . But that’s not what we want. A symlink may be a folder, but we are only concerned with the name.
The main benefit of rm over unlink is that you can remove multiple symlinks at once, like you can with files.
How to Find and Delete Broken Links
Broken links occur when the file or folder that a symlink points to changes path or is deleted.
For example, if ‘transactions.txt’ moves from /home/james to /home/james/personal , the ‘trans.txt’ link becomes broken. Every attempt to access to the file will result in a ‘No such file or directory’ error. This is because the link has no contents of its own.
When you discover broken links, you can easily delete the file. An easy way to find broken symlinks is:
This will list all broken symlinks in the james directory – from files to directories to sub-directories.
Passing the -delete option will delete them like so:
find /home/james -xtype l -delete
Wrapping up
Symbolic link are an interesting feature of Linux and UNIX systems.
You can create easily accessible symlinks to refer to a file or folder that would otherwise not be convenient to access. With some practice, you will understand how these work on an intuitive level, and they will make you much more efficient at managing file systems.
Dillion Megida
Developer Advocate and Content Creator passionate about sharing my knowledge on Tech. I simplify JavaScript / ReactJS / NodeJS / Frameworks / TypeScript / et al My YT channel: youtube.com/c/deeecode
If you read this far, tweet to the author to show them you care. Tweet a thanks
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charity organization (United States Federal Tax Identification Number: 82-0779546)
Our mission: to help people learn to code for free. We accomplish this by creating thousands of videos, articles, and interactive coding lessons — all freely available to the public. We also have thousands of freeCodeCamp study groups around the world.
Donations to freeCodeCamp go toward our education initiatives, and help pay for servers, services, and staff.
Replace Symbolic Links with Files
I have a bunch of symbolic links to another drive. I need move all files off of that drive that are referenced elsewhere so I can remove it.
16 Answers 16
For some definitions of «easy»:
#!/bin/sh set -e for link; do test -h "$link" || continue dir=$(dirname "$link") reltarget=$(readlink "$link") case $reltarget in /*) abstarget=$reltarget;; *) abstarget=$dir/$reltarget;; esac rm -fv "$link" cp -afv "$abstarget" "$link" || < # on failure, restore the symlink rm -rfv "$link" ln -sfv "$reltarget" "$link" >done
Run this script with link names as arguments, e.g. through find . -type l -exec /path/tos/script <> +
Thanks for the edit, anon, but the script does handle filenames with spaces just fine, by quoting variables in all necessary places. Changing «$var» to «$» is a noop in sh/bash. I removed the one bashism ( [[ ), the rest is compatible with POSIX sh.
An even more robust method for handling symlink failures is to cp to a temporary file in the same directory then mv -f that temporary file into the original. This should guard against problems like people holding down Ctrl-C or the filesystem filling up between the rm and cp commands (thus preventing even the new ln from working). Temporary filenames are easy to spot with ls -a for later cleanup if needed.
As a side note, I seriously can’t remember why I didn’t just use abstarget=$(readlink -f «$link») instead of the case block, but it might have been portability reasons.
If I understood you correctly the -L flag of the cp command should do exactly what you want.
Just copy all the symlinks and it will replace them with the files they point to:
cp -L file tmp/ && rm file && mv tmp/file .
Thanks — almost what I needed: I had to do something like: cp -L files tmp/ && rm files && cp tmp/files . If you clarify, you’ll probably help more people.
Might be easier to just use tar to copy the data to a new directory.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
You could use something like this
tar -hcf - sourcedir | tar -xf - -C newdir tar --help: -H, --format=FORMAT create archive of the given format -h, --dereference follow symlinks; archive and dump the files they point to
I love your solution, but I don’t understand the last part of your message. For me you should do : tar -hcf — sourcedir | tar -xf — -C newdir
@Everyone: Use -h rather than -H , because -H is specific to bsdtar and is not supported by GNU tar. Also, it only follows symlinks given on the command line, but we want to follow all symlinks in sourcedir. (Posting as a comment because my suggested edit was rejected.)
find ./ -type l -exec sh -c 'for i in "$@"; do cp --preserve --remove-destination "$(readlink -f "$i")" "$i"; done' sh <> +
based on https://superuser.com/a/1301199/499386 of MastroGeppetto and with edits from @tom
«easy» will be a function of you, most likely.
I’d probably write a script that uses the «find» command line utility to find symbolically linked files, then calls rm and cp to remove and replace the file. You’d probably do well to also have the action called by find check that there’s enough free space left before moving the sym link too.
Another solution may be to mount the file system in question through something that hides the sym links (like samba), then just copy everything out of that. But in many cases, something like that would introduce other problems.
A more direct answer to your question is probably «yes».
Edit: As per the request for more specific info. According to the man page for find, this command will list all sym link files in to a depth of 2 directories, from /:
find / -maxdepth 2 -type l -print
To get find to execute something on finding it:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh <> \;
I believe that’ll call some script I just made up, and pass in the file name you just found. Alternatively, you could capture the find output to file (use «find [blah] > symlinks.data», etc) then pass that file in to a script you’ve written to handle copying over the original gracefully.