How to find Mac documents path (language independent) - macos

I need to find the documents folder path using golang on MacOS. I can do like this:
docsPath := os.Getenv("HOME") + "/Documents"
But I don't know if "Documents" is a valid solution for other OS languages. What if the Mac is Italian language? Is there a way to find out for sure? Or where can I find the proven information that it is always "Documents"? Sadly I do not have access to any Mac other than English.

MacOS places all user files and folders to /Users/%username%/, e.g. for me /Users/lisitsky.
Documents are located at subfolder /Users/username/Documents. You look at it name in terminal by ls /Users/username/Documents.
Finder shows localized names for standard folders in your language but uses standard names on system level.
Also you may check os/user module.
func main() {
usr, _ := user.Current()
dir := usr.HomeDir
fmt.Println(dir, path.Join(dir, "Documents"))
}

Related

filepath Base on windows not working after cross compilation (Golang)

If I have a path on linux/OSX such as filepath := /Users/jamesbond/some/where/file.txt
then I can do
name := path.Base(filepath)
and name will be file.txt
however on windows this does not work. The returned value of name is still /Users/jamesbond/some/where/file.txt
I guess I can see why, as the function base has
for len(path) > 0 && path[len(path)-1] == '/' {
path = path[0 : len(path)-1]
}
i.e its clearly really only setup for linux/OSX style file paths.
I am cross compiling from OSX for windows. I guess that the library on windows has the corect / in the SDK, but how can I handle this regardless of OS? Is there a way to convert or something before, then use Base function?
What would be the recommended way to write this code once and it work on all OSes?

Find location of Golang application

I have a Golang application which is being deployed into a container via Kubernetes. Within the service I would like to read a file which is nested within the application.
I'm struggling to find out how to set the current working directory to the location of the application.
Currently the application panics with an error due to the relative paths not being aligned:
open /workspace/source/package/file.csv: no such file or directory
I've tried using the following code and appending the file name:
var (
_, b, _, _ = runtime.Caller(0)
basepath = filepath.Dir(b)
)
However this still doesn't work. Is there a way to find the applications current location and then append the filename?
Thanks for help!
Use os.Executable to find the path to the executable.
b, err := os.Executable()
if err != nil {
log.Fatal(err)
}
basepath := filepath.Dir(b)
Can't you just cd before executing the application? Then you can use relative paths.

Golang os.Rename(<fromDir>,<toDir>) not working in Windows

Using Go - lang, according to the documentation, the os.Rename should be able to rename either a file or directory on any operating system.
On Linux it works as it should, pass either a file or directory into it and the file or directory are moved.
On windows i recieve an 'Access is denied' Error when trying to pass a folder.
It works 100% for files.
example:
source = c:\sourcefolder
destination = c:\destinationfolder
source contains:
C:\sourcefolder\file1.xml
C:\sourcefolder\file2.xml
C:\sourcefolder\foldername1
C:\sourcefolder\foldername1\file3.xml
C:\sourcefolder\foldername2
C:\sourcefolder\foldername2\file4.xml
both file1.xml and file2.xml will successfully copy to c:\destination.
But the folders and files within the folders crash out with access denied
The script is pretty simple:
source := "C:\\sourcefolder"
destination := "C:\\destinationfolder"
pathSeperator := "\\"
files, err := ioutil.ReadDir(source)
if err != nil {
fmt.Println("Move command execution error: ", err)
}
for _, f := range files {
fmt.Println(f.Name())
fmt.Println(f.Mode())
err := os.Rename(source+pathSeperator+f.Name(), destination+pathSeperator+f.Name())
if err != nil {
fmt.Println("Move command execution error: ", err)
panic(err)
}
}
Having searched stackoverflow and golang's resources, i found the issue listed in 2016 that reported this fault and according to the issue it was fixed, but i am unable to get this to work. Nowhere else that i can find lists this issue go golang.
checking the f.Mode for access, i get drwxrwxrwx and have complete access to all the files and directories.
Any help with this would be great, racking my mind. Thank you.
Quoted from comment. solved my issue.
Found the cause of the fault to be, if a windows explorer window is
open and has ANY visibility of the folders being moved (i.e. in the
tree on the left or right-pane) then access is denied as it can not
move the folders. If i minimize all the tree's so that the
source\destination folders are not visible and select a different sub
folder in windows explorer then the os.Rename works as it should,
moving all content from A to B really quick (as per linux)
I had the same issue with copying files within the same folder. The following solution works just fine (without closing or minimizing windows):
// read original file
origFile, _:= os.ReadFile(filePath)
// create new file with a different name
newFile, _ := os.Create(filePath + ".new")
// print data from original file to new file.
fmt.Fprintf(newFile, "%s", string(origFile))

How to get the parent directory path of a path in FreePascal/Lazarus?

I have a path to a directory saved as a string, and wanted to know how I can easily and robustly extract the parent directory from this string?
I tried to see if there is some method for this in FileUtil and SysUtils, but haven't found anything so far.
The simplest way is to find the last path delimiter character and trim the source string. BTW there are some alternative:
program Project1;
uses
sysutils;
var
sExe: string;
sParent: string;
sParentProper: string;
begin
sExe := ExtractFilePath(ParamStr(0)); // Get executable directory
Writeln(sExe);
sParent := IncludeTrailingPathDelimiter(sExe) + '..' + PathDelim; // Make parent path for executable
Writeln(sParent);
sParentProper := ExpandFileName(sParent); // Get absolute path based on relative path
WriteLn(sParentProper);
Readln;
end.
And output is:
C:\Users\nd\AppData\Local\Temp\
C:\Users\nd\AppData\Local\Temp\..\
C:\Users\nd\AppData\Local\
So using this technique the proper way is ExpandFileName(IncludeTrailingPathDelimiter(sBasePath) + '..')
PS: We are using only sysutils unit so it is pure FPC solution and it is not require any LCL libraries.
An even simpler way to do this would be:
parentDirPath := ExtractFilePath(ExcludeTrailingPathDelimiter(thePath));
This works on the three major platforms (Linux, Mac OS X and Windows), and thePath may refer to a file or a folder.
Well, I of course figured it out only after asking about it here:
parentDirPath := FileUtil.ExtractFileNameOnly(
FileUtil.ChompPathDelim(theSubDirPath));
... will do!
The FileUtil.ChompPathDelim() part is necessary to "fool" FPC to believe the top folder is a "file" (so no trailing slash allowed).

How do I find iTunes library folder on Mac and Windows?

I made an application that parse the iTunes library to retrieve its content. It works fine in most cases but if a user moved his library somewhere else than the default iTunes folder (see: http://lifehacker.com/238296/ultranewb--how-to-move-your-itunes-library-to-an-external-drive), then I need a way to find this path.
On Mac, I was looking into ~/Library/Preferences/com.apple.iTunes.plist. There is a setting called "alis:1:iTunes Library Location" but it contains several parameters all concatenated and converted to hexadecimal.
On Windows, I found this file "C:\Documents and Settings\\Application Data\Apple Computer\iTunes\iTunesPrefs.xml" that contains a setting "iTunes Library XML Location:1" but this one is encoded.
Any help would be greatly appreciated.
Thanks!
On Windows, the iTunes Library XML Location:1 entry in iTunesPrefs.xml is a Base 64 encoded Unicode string, so you'll need to decode it before you can use it. On my PC, it decodes to C:\Documents and Settings\Emerick\My Documents\My Music\iTunes\iTunes Music Library.xml.
It should be relatively easy to decode this value using your language of choice; your platform may even provide utility libraries that make this trivial. In C#, for example, the decoding function would look something like this:
static public string DecodeBase64(string encodedData)
{
byte[] encodedBytes = System.Convert.FromBase64String(encodedData);
return System.Text.UnicodeEncoding.Unicode.GetString(encodedBytes);
}
I can't help you with the Windows stuff, but on the Mac what you're seeing in that prefs file is old-school alias handle data. Take a look at or just use Chris Hanson's BDAlias class to convert it to a path.
http://github.com/rentzsch/bdalias
As the others point out "alis:1:iTunes Library Location" is alias data. Here's how I find the path from the data in OS X using Python.
#!/usr/bin/env python
import commands, plistlib
from Carbon import File
from os.path import expanduser
PLIST_PATH = '~/Library/Preferences/com.apple.iTunes.plist'
PLIST_KEY = 'alis:1:iTunes Library Location'
def resolve_path_from_alias_data( alis ):
fs_ref = File.Alias( rawdata=alis ).FSResolveAlias( None )[0]
file_path = fs_ref.as_pathname()
return file_path
plist_str = commands.getoutput( '/usr/bin/plutil -convert xml1 -o - "' + expanduser( PLIST_PATH ) + '"' )
plist_data = plistlib.readPlistFromString( plist_str )
alis_data = plist_data[ PLIST_KEY ].data
file_path = resolve_path_from_alias_data( alis_data )
print repr( file_path )
Unfortunately, iTunes no longer uses "alis:1:iTunes Library Location" so this no longer works. Now iTunes 11 uses an entry called "RDoc:132:Documents" which seems to be completely different. I have posted a similar question with the appropriate iTunes 11 details.
Actually, my answer works just fine as of OS X 10.9.1. I'm not sure whether it stopped due to some error I made, or if Apple quietly reverted something. Either way, it's working again on my Mac.

Resources