How to copy symbolic link file from Linux to Windows and then back to Linux but still keeping it as a symbolic link
In *nix a symlink is typically just a plain text file with a "symlink" attribute. The file contains the path to the link target. The "symlink" attribute does not exist on Windows. So when you extract the symlink on Windows, it becomes a regular text file [though it may also error, it may depend on a tool you use to extract the archive]. When copied back to *nix, it stays a regular text file.
The only solution would be to keep the "symlink" attribute in some external metadata store and restore the attribute when uploading the file or creating the archive.
Though I'm not aware of any tool that supports this.
You can definitely code this.
Using WinSCP: You make a code that generates WinSCP script. The code would recursively iterate a local directory structure. For a file it will generate the
put
command to upload it. For a symlink it will generate theln
command to create a symlink. To distinguish the symlink, you can maybe use just a simple heuristics (symlink = a short one-line text file with slashes). A proper way would be to remember the file symlink attribute when extracting the archive (but you would have to code the extraction yourself too then, see also a hint below).Using archive:
I recently implemented this for a ZIP archive. (Even on Windows) You can use the PHP methodZipArchive::setExternalAttributes
to flag an archived file as a symlink. Note that the function is available since PHP 5.6 only.Sample code:
$symlink = true; // is symlink?
$dir = false; // is folder?
$mode = "755"; // permissions
$local_path = "C:\\zip\\folder\\mylink";
$zip_path = "folder/mylink";
$attr =
(1 << 14) | // this bit seems to be always set
(1 << ($dir ? 30 : 31)) |
($symlink ? (1 << 29) : 0) |
octdec($mode) << 16;
$zip->addFile($local_path, $zip_path);
$zip->setExternalAttributesName($zip_path, ZipArchive::OPSYS_UNIX, $attr);If you are more familiar with Python, see How do I set permissions (attributes) on a file in a ZIP file using Python's zipfile module? It deals with permissions only, but you can easily extend it with the symlink bit, as per my PHP example.
How to convert symlink to regular file?
There is no single command to convert a symlink to a regular file. The most direct way is to use readlink
to find the file a symlink points to, and then copy that file over the symlink:
cp --remove-destination `readlink bar.pdf` bar.pdf
Of course, if bar.pdf
is, in fact, a regular file to begin with, then this will clobber the file. Some sanity checking would therefore be advisable.
How to copy a directory with symbolic links and resolve them?
cp -rL /source /destination
r = recursive
L = follow and expand symlinks
linux cp: how to have it follow links but not stop if a link target doesn't exist
With the standard GNU toolchain, no, there's no way.
You could instead copy your files, keeping symlinks as symlinks, then use find -follow -type l -delete
to delete the broken symlinks, and then copy again, this time following symlinks.
Of course, you could also just write a python etc. program to do the copy for you, or find all files in the original trees that are not broken symlinks and use these with cp, replacing parts of the path with the target path using sed
:
find -type d|sed 's/^\(.*\)/"\1" "\/target\/\1"/g'|xargs -p mkdir
find -follow -not -type l -not -type d|sed 's/^\(.*\)/"\1" "\/target\/\1"/g'|xargs -n2 cp
sed will duplicate your found file path, prefixing it with the target directory.
Git symbolic links in Windows
You can find the symlinks by looking for files that have a mode of 120000
, possibly with this command:
git ls-files -s | awk '/120000/{print $4}'
Once you replace the links, I would recommend marking them as unchanged with git update-index --assume-unchanged
, rather than listing them in .git/info/exclude
.
How do I move a relative symbolic link?
You can turn relative paths into full paths using readlink -f foo
. So you would do something like:
ln -s $(readlink -f $origlink) $newlink
rm $origlink
EDIT:
I noticed that you wish to keep the paths relative. In this case, after you move the link, you can use symlinks -c
to convert the absolute paths back into relative paths.
Related Topics
System Calls: Difference Between Sys_Exit(), Sys_Exit and Exit()
Bash: Start Remote Python Application Through Ssh and Get Its Pid
Copying an Image to The Clipboard from Command Line
How to Open Multiple Instances of a Program in Linux
How Is an Error Reported from Async Socket Connect
Does Anyone Know Where to Define The Hardware, Revision and Serial No. Fields of /Proc/Cpuinfo
Kate Text Editor Cannot Handle Lines Longer Than 1024
How to Type "Cargo Run" Without Needing to Set The Ld_Library_Path Shell Variable
Shared Library Symbol Conflicts and Static Linking (On Linux)
Finding Directories with Find in Bash Using a Exclude List
Docker Run Groupadd && Useradd Directives Have No Effect
How to Set Environment Variable in Linux Permanently
Docker - Eacces: Permission Denied, Mkdir '/App/Node_Modules/.Cache'
Goroutine in Io Wait State for Long Time
Why Does Munmap Needs a Length as Parameter
How to Highlight The Differences Between Subsequent Lines in a File
List Files That Are in Directory1 But Not in Directory2 and Vice Versa