Creating Hard Link with an Dialog - OneDrive

Hi All,

I am working on a script which will create an Hard link to OneDrive with an UI option to choose folder(from the User Profile) to sync with OneDrive.

This the perl command that i am using to create Hard link in Mac:

So far I am not successful in doing this and seeing the below error:

Please suggest!!

on run
	--Get the folder
	set theFolder to (path to home folder) as text
	
	--Get the path to de destination folder of the files
	
	set destination_folder to (((path to home folder) as text) & "OneDrive - Company Systems Inc") as alias
	
	--Generate the list of files inside theFolder
	tell application "Finder"
		set theItems to items of folder theFolder
		set theNames to {}
		repeat with anItem in theItems
			set end of theNames to name of anItem
		end repeat
	end tell
	
	--Let user select the files of the list
	choose from list theNames with prompt "Pick the items you want to copy from:" & return & theFolder OK button name "Copy" cancel button name "Quit" with multiple selections allowed
	
	tell result
		if it is false then error number -128 -- cancel
		set theChoices to it
	end tell
	
	if (count of theChoices) is greater than or equal to 1 then
		repeat with aChoice in theChoices
			set thisItem to (theFolder & aChoice) as alias
			-- do something with thisItem
			do shell script "perl -e 'link " & thisItem & ", " & destination_folder & " /Music '"
		end repeat
	end if
end run

Hello

You are passing aliases to your do shell script command.
This one can’t work with this class of objects.
You must coerce them as POSIX path.
As at least one of the passed pathnames contain space characters, I added the “quoted form” action so that your path would be treated correctly.

on run
	--Get the folder
	set theFolder to (path to home folder) as text
	
	--Get the path to de destination folder of the files
	
	set destination_folder to quoted form of POSIX path of (((path to home folder) as text) & "OneDrive - Company Systems Inc") # EDITED so that do shell script will be happy
	
	--Generate the list of files inside theFolder
	tell application "Finder"
		set theItems to items of folder theFolder
		set theNames to {}
		repeat with anItem in theItems
			set end of theNames to name of anItem
		end repeat
	end tell
	
	--Let user select the files of the list
	choose from list theNames with prompt "Pick the items you want to copy from:" & return & theFolder OK button name "Copy" cancel button name "Quit" with multiple selections allowed
	
	tell result
		if it is false then error number -128 -- cancel
		set theChoices to it
	end tell
	
	if (count of theChoices) is greater than or equal to 1 then
		repeat with aChoice in theChoices
			set thisItem to quoted form of POSIX path of (theFolder & aChoice) # EDITED so that do shell script will be happy
			-- do something with thisItem
			do shell script "perl -e 'link " & thisItem & ", " & destination_folder & " /Music '"
		end repeat
	end if
end run

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 14 décembre 2016 17:15:36

Thanks Yvan!!

Tried with the changed one, but still seeing some other error while running the script:

From the “user selection list(folder slection)” I am just selecting “Music” from the list to get it Hardlinked to OneDrive as an testing, thats why I am including “Music” folder name after the “destination_folder” in the below command. Not sure how to handle when multiple folders are selected.

do shell script (“/usr/bin/perl -e ‘link " & thisItem & ", " & destination_folder & "/Music’”)

If i am just running this command from Terminal there is no issue… here is the command:

/usr/bin/perl -e ‘link “/Users/kumar/Music”, “/Users/kumar/OneDrive - Company Systems Inc/Music”’

Please suggest.

I apologize but I’m not at ease with do shell script.

I was able to generate hardlinks with :

In the script below I use two do shell script instructions to create hardlinks but I don’t like them because they can’t create hardlinks to folders

My preferred scheme is the one using ASObjC.

use AppleScript version "2.3.1"
use framework "Foundation"
use scripting additions

# two handlers borrowed from Shane STANLEY's FileManagerLib.scptd
on createHardLinkInFolder:folderPath linkedTo:originalFileOrPath
	set folderPathURL to my makeURLFromFileOrPath:folderPath
	set originalURL to my makeURLFromFileOrPath:originalFileOrPath
	set linkName to originalURL's |lastPathComponent|()
	set theLinkURL to folderPathURL's URLByAppendingPathComponent:linkName
	set theFileManager to current application's NSFileManager's |defaultManager|()
	set {theResult, theError} to theFileManager's linkItemAtURL:originalURL toURL:theLinkURL |error|:(reference)
	if not (theResult as boolean) then error (theError's |localizedDescription|() as text)
end createHardLinkInFolder:linkedTo:

-- This handler is called by other handlers
on makeURLFromFileOrPath:theFileOrPathInput
	-- make it into a Cocoa object for easier comparison
	set theFileOrPath to item 1 of (current application's NSArray's arrayWithObject:theFileOrPathInput)
	if (theFileOrPath's isKindOfClass:(current application's NSString)) as boolean then
		if (theFileOrPath's hasPrefix:"/") as boolean then -- full POSIX path
			return current application's class "NSURL"'s fileURLWithPath:theFileOrPath
		else if (theFileOrPath's hasPrefix:"~") as boolean then -- POSIX path needing ~ expansion
			return current application's class "NSURL"'s fileURLWithPath:(theFileOrPath's |stringByExpandingTildeInPath|())
		else -- must be HFS path
			return current application's class "NSURL"'s fileURLWithPath:(POSIX path of theFileOrPathInput)
		end if
	else if (theFileOrPath's isKindOfClass:(current application's class "NSURL")) as boolean then -- happens with files and aliases in 10.11
		return theFileOrPath
	else -- must be a file or alias
		return current application's class "NSURL"'s fileURLWithPath:(POSIX path of theFileOrPathInput)
	end if
end makeURLFromFileOrPath:

set destFolder to POSIX path of (path to desktop)

set originalItem to POSIX path of (path to scripts folder from user domain as text)

my createHardLinkInFolder:destFolder linkedTo:originalItem

set originalItem2 to POSIX path of ((path to scripts folder from user domain as text) & "Delete Diagnostics.scpt")
do shell script "ln " & quoted form of originalItem2 & " " & quoted form of destFolder

set originalItem3 to POSIX path of ((path to scripts folder from user domain as text) & "unhide all.scpt")
do shell script "link " & quoted form of originalItem3 & " " & quoted form of destFolder

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 14 décembre 2016 20:47:32

I’m sorry, I don’t have time at the moment to combine bits here with your script to make it work with hard links. But I already had an Applescript that makes symlinks, and thought it might be handy for you to reference. Will get back to this later and contribute more if I can find time.

on connect_scripting_additions()
	--The script makes a symlink to the dropbox shared "Scripting Additions" folder named "Scripting Additions" in the user library folder
	
	
	set userPath to the POSIX path of (path to home folder)
	set libraryLinkPath to userPath & "Library/Script Libraries" -- path for symlink
	set dropboxPath to userPath & "Dropbox/Clipart Project/Scripts/Script Libraries" -- path for the shared dropbox folder
	
	try
		set testDropboxPath to POSIX file dropboxPath as alias
	on error
		display dialog "Could not find the shared Dropbox Script Libraries folder at " & dropboxPath & "." & return & "Check that you're connected to the shared \"Scripts\" folder." buttons {"Darn"} default button "Darn"
	end try
	
	set conflictChoice to ""
	
	try
		set testLibraryPath to POSIX file libraryLinkPath as alias
		set conflictChoice to the button returned of (display dialog "An existing \"Script Libraries\" folder was found in your User Library. This needs to be replaced with a link to the shared Dropbox Copy." buttons {"Stop", "Delete Existing Library", "Move Existing Library to Desktop"} default button "Delete Existing Library")
	end try
	
	tell application "Finder"
		if conflictChoice is "Delete Existing Library" then
			do shell script "rm -r " & quoted form of libraryLinkPath
		else if conflictChoice is "Move Existing Library to Desktop" then
			do shell script "mv " & quoted form of libraryLinkPath & " '/Volumes/Hackintosh HD/Users/tspoon/Desktop/'"
		else if conflictChoice is "Stop" then
			return
		end if
	end tell
	
	"/Volumes/Hackintosh HD/Users/tspoon/Desktop"
	
	
	do shell script "ln -s " & quoted form of dropboxPath & " " & quoted form of libraryLinkPath
	
	delay 0.1
	
	try
		run script "
use scripting additions
tell script \"ROT Additions\" to check_this_scripting_addition()
"
	on error
		display dialog "Something seems to have gone wrong with the link."
	end try
end connect_scripting_additions

@Kumar

Are you sure that what you posted as a valid terminal command :
[format]/usr/bin/perl -e ‘link “/Users/kumar/Music”, “/Users/kumar/OneDrive - Company Systems Inc/Music”’[/format]
really do its duty.

When I run a similar one here:
[format]/usr/bin/perl -e ‘link “/Users/yvankoenig/Library/Scripts/Maybe.scpt”, “/Users/yvankoenig/Desktop/”’[/format]

it issue no error but there is no hardlink created in the desktop folder.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 15 décembre 2016 10:14:59

Yvan,

Terminal command was failing because you have not added… what you want to hardline in the destination (Maybe.scpt).

/usr/bin/perl -e ‘link “/Users/yvankoenig/Library/Scripts/Maybe.scpt”, “/Users/yvankoenig/Desktop/Maybe.scpt”’

Thanks.

With this added info I was able to write the code required to use the perl command in a do shell script instruction.

# hardlink to a file
set fileName to "May be.scpt"

set linkPath to POSIX path of ((path to desktop as text) & fileName)

set originalItem to POSIX path of ((path to scripts folder from user domain as text) & fileName)

do shell script "/usr/bin/perl -e " & quoted form of ("link " & quote & originalItem & quote & ", " & quote & linkPath & quote)


# Now hardlink to a folder
set linkPath to POSIX path of ((path to desktop as text) & "Scripts")

set originalItem to POSIX path of (path to scripts folder from user domain as text)

do shell script "/usr/bin/perl -e " & quoted form of ("link " & quote & originalItem & quote & ", " & quote & linkPath & quote)

It’s execution is awfully longer than the scheme using ASObjC.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 15 décembre 2016 13:41:21

Why are you using perl, guys?

/bin/ln without the -s switch does the same:

do shell script "/bin/ln " quoted form of source & space & quoted form of destination

Will the Hard link work for directory? I think now it will only work for a file…

I am seeing following error while running the ln command:

Hello Stefan

I carefully wrote that ln or link doesn’t apply to create a link to a folder.
It’s why I use ASObjC code.

For the perl code, I was just trying to respond to the original question (and its added explanations) which was explicitly upon perl, probably because the hardlink was pointing upon a folder.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 15 décembre 2016 16:01:35

This is my destination path variable, here is the actual destiny path: “/Users/kumar/OneDrive -Systems Inc/”

Here I am trying to set new destination path by adding the Users selected choice… to the end of destination path (when any folder from User Profile is selected) in this example I have selected “Music” folder.

when I am trying to echo result of variable newdestiny I am seeing the destination result path as:

Any idea how can I remove the single quotes after the OneDrive - System Systems Inc path? this is making the script to fail.

If I am just running my command without any defined variable… it works fins and creates Hard link without any error:

Thanks!!

Very simple.

set destination_folder to  POSIX path of (((path to home folder) as text) & "OneDrive - Systems Inc")
set newdestiny to quoted form of (destination_folder & "/Music")
set destination_folder to quoted form of destination_folder

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 15 décembre 2016 19:02:47

Thanks Yvan, your trick worked for me in adding additional path to the variable and in removing the quotes.

when I am trying the to implement directory hardlinks using the command line utility provided in this link:
https://github.com/selkhateeb/hardlink it works fine when implemented on the below script:

But i am still seeing the below error while implementing the Hard link using perl:

Also tried with your provided code :

Command will look like this… following the above one:

While running the above code I am seeing this error:

set theFolder to quoted form of POSIX path of (((path to home folder) as text) & "Music")

-- do shell script "echo " & theFolder & ""

set destination_folder to POSIX path of (((path to home folder) as text) & "OneDrive - Systems Inc")

set newdestiny to quoted form of (destination_folder & "/Music")

-- do shell script "echo " & newdestiny & ""

-- Hard link with hln utility works fine:
-- do shell script "/usr/local/bin/hln " & theFolder & " " & newdestiny & " "

--Hard link with perl command is failing:
do shell script "/usr/bin/perl -e 'link \"" & theFolder & "\", \"" & newdestiny & "\" '"


I can’t help you more than saying : move back to message #8 and read it carefully.

What you posted doesn’t match what I wrote in the referenced message.

Maybe added comments would help:

# hardlink to a file
set fileName to "May be.scpt"

set linkPath to POSIX path of ((path to desktop as text) & fileName) # NOT QUOTED !

set originalItem to POSIX path of ((path to scripts folder from user domain as text) & fileName) # NOT QUOTED !

do shell script "/usr/bin/perl -e " & quoted form of ("link " & quote & originalItem & quote & ", " & quote & linkPath & quote)


# Now hardlink to a folder
set linkPath to POSIX path of ((path to desktop as text) & "Scripts") # NOT QUOTED !

set originalItem to POSIX path of (path to scripts folder from user domain as text) # NOT QUOTED !

do shell script "/usr/bin/perl -e " & quoted form of ("link " & quote & originalItem & quote & ", " & quote & linkPath & quote)
# Your code :
set theFolder to quoted form of POSIX path of (((path to home folder) as text) & "Music")

set destination_folder to POSIX path of (((path to home folder) as text) & "OneDrive - Systems Inc")

set newdestiny to quoted form of (destination_folder & "/Music")

"'link \"" & theFolder & "\", \"" & newdestiny & "\" '"

--> "'link "'/Users/yvankoenig/Music'", "'/Users/yvankoenig/OneDrive - Systems Inc/Music'" '"

# What I posted :

set theFolder to POSIX path of (((path to home folder) as text) & "Music") # NOT QUOTED

set destination_folder to POSIX path of (((path to home folder) as text) & "OneDrive - Systems Inc")

set newdestiny to (destination_folder & "/Music") # NOT QUOTED

"'link \"" & theFolder & "\", \"" & newdestiny & "\" '"

--> "'link "/Users/yvankoenig/Music", "/Users/yvankoenig/OneDrive - Systems Inc/Music" '"

Of course I dropped the beginning of the instructions because your folders don’t exist on my machine !
I hope that you will see the differences between both codes.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 16 décembre 2016 14:29:38

Thanks you Yvan! sorry I took time to look into this.

I was able to compile the hard link command on both create hard link and remove hard link script:

here is my complete script (Creating hard link)

on run
	--Get the folder
	set theFolder to (path to home folder) as text
	
	--Get the path to de destination folder of the files
	set destination_folder to POSIX path of (((path to home folder) as text) & "OneDrive -Company Systems Inc")
	
	--Generate the list of files inside theFolder
	tell application "Finder"
		set theItems to items of folder theFolder
		set theNames to {}
		repeat with anItem in theItems
			set end of theNames to name of anItem
		end repeat
	end tell
	
	--Let user select the files of the list
	choose from list theNames with prompt "Pick the items you want to copy from:" & return & theFolder OK button name "Hard link" cancel button name "Quit" with multiple selections allowed
	
	tell result
		if it is false then error number -128 -- cancel
		set theChoices to it
	end tell
	
	if (count of theChoices) is greater than or equal to 1 then
		repeat with aChoice in theChoices
			set thisItem to POSIX path of (theFolder & aChoice) as text
			do shell script "echo " & thisItem & ""
			set newdestiny to POSIX path of (destination_folder & "/" & aChoice) as text
			do shell script "echo " & newdestiny & ""
			-- do something with thisItem
			set the_result to do shell script "/usr/bin/perl -e " & quoted form of ("link " & quote & thisItem & quote & ", " & quote & newdestiny & quote)
			
		end repeat
	end if
end run

And this one is to removing hard link:

on run
	--Get the folder
	set theFolder to (path to home folder) as text
	
	--Get the path to de destination folder of the files
	
	set destination_folder to POSIX path of (((path to home folder) as text) & "OneDrive - Company Systems Inc")
	
	--Generate the list of files inside theFolder
	tell application "Finder"
		set theItems to items of folder theFolder
		set theNames to {}
		repeat with anItem in theItems
			set end of theNames to name of anItem
		end repeat
	end tell
	
	--Let user select the files of the list
	choose from list theNames with prompt "Pick the items you want to copy from:" & return & theFolder OK button name "Remove Hard Link" cancel button name "Quit" with multiple selections allowed
	
	tell result
		if it is false then error number -128 -- cancel
		set theChoices to it
	end tell
	
	if (count of theChoices) is greater than or equal to 1 then
		repeat with aChoice in theChoices
			set thisItem to POSIX path of (theFolder & aChoice) as text
			do shell script "echo " & thisItem & ""
			set newdestiny to POSIX path of (destination_folder & "/" & aChoice) as text
			do shell script "echo " & newdestiny & ""
			-- do something with thisItem
			set the_result to do shell script "/usr/bin/perl -U -e " & quoted form of ("unlink " & quote & newdestiny & quote) with administrator privileges
		end repeat
	end if
end run