Golang os.Rename(<fromDir>,<toDir>) not working in Windows - 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))

Related

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 beginner, on Windows: System cannot find file specified

Only just now starting with golang, with only a small amount of programming experience before this. I'm trying to create a script that will summarize certain things from a csv file, but I haven't even gotten past testing out file reading yet.
I was having trouble reading the excel files, and kept getting the "System cannot find file specified" error. So I thought I'd see if I could at least get it to read a simple text file, using an example from golangbot, which looks like this:
package main
import (
"fmt"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("test.txt")
if err != nil {
fmt.Println("File reading error", err)
return
}
fmt.Println("Contents of file:", string(data))
}
That simple. The text file is located within the same folder (in %USERPROFILE%/go/src, and /go/ is my GOPATH) as the actual code file I'm attempting to run, and yes, it is called "test.txt". Yet, every attempt to run gives me the same error message, that the system cannot find the specified file (test.txt).
Running any other kind of .go file or building one from this location works just fine. I'm seen others with this error, but it seemed like it was always to do with the GOPATH being set wrong.
I'm frustrated that I even have to ask about something like this, but it's all I could think of right now. Is there something wrong with the locations of my files or the GOPATH itself, or is this something different?
Thank you
Welp, the problem was solved. Turns out, the actual name of the txt file was test.txt.txt. Thanks to notepad and my own lack of awareness.
Bit embarrassing, really. Changing the name worked.
when you are trying this with your notepad. Be cautious while saving it.
The file type should be compatible
File -> save as >
FileName : FileName.go
Save as type : All Files
Now execute as ("folder path">go run FileName.go
Then the result. Kudos
I have been having a similar issue as well. I would try to do this in order to fix it. delete the file and create a new one. That is a simple solution in my opinion. Make sure to copy the code and then paste onto the new file. Mkdir
cd into that directory touch or nano
create a new file. then open that file. then do go run that file name.
it should work.

Binary and additional files

I'm trying to package my go application binary which is accessible by a web interface running on localhost:8080 so that when downloaded it's able to find the JS(front-end) files in the folder where the file is ran but i can't seem to make it work.
I've been doing something like this :
pwd, err := os.Getwd()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
Then trying to use the working directory of the binary to access the files inside it but that doesn't seem to work.
The binary is located at :
/Users/admin/Desktop/testappfolder
but when i run the program with just :
pwd, err := os.Getwd()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(pwd)
I end up getting /Users/admin as the working directory instead.
I wondering :
Where i'm going wrong ?
Is this has something to do with the Gopath ?
Am i going at it the right way regarding distributing the app as a "zip" and having file path setup directly inside my program relative to the working directory ? or is it that logic that's wrong ?
os.Getwd is going to correspond to where you start your binary from not where the binary is located.
To make for a more robust solution I would pass in the location of the files directory using a flag or using a config value.

File path in golang

I have a project with next structure:
|_main.go
|_config
|_config.go
|_config_test.go
|_config.json
I'm having next code line in config.go:
file, _ := os.Open("config/config.json")
When I'm executing method contained this code line from main.go all is working. But when I'm trying to execute this method from config_test.go it produces error:
open config/config.json: no such file or directory
As I understood it is a working directory issue because I'm launching same code with relative path from different directories. How can I fix this problem without using full path in config.go?
Relative paths are always resolved basis your current directory. Hence it's better to avoid relative paths.
Use command line flags or a configuration management tool (better approach) like Viper
Also according to The Twelve-Factor App your config files should be outside your project.
Eg usage with Viper:
import "github.com/spf13/viper"
func init() {
viper.SetConfigName("config")
// Config files are stored here; multiple locations can be added
viper.AddConfigPath("$HOME/configs")
errViper := viper.ReadInConfig()
if errViper != nil {
panic(errViper)
}
// Get values from config.json
val := viper.GetString("some_key")
// Use the value
}

Checking with os.Stat vs just os.MkdirAll

I need to write to a file in a nested directory that may or may not exist.
At first, I checked if the folder existed via os.Stat, doing os.MkdirAll if it doesn't exist, and then opening and writing to a file.
I tried removing the os.Stat and just doing os.MkdirAll, and it appears to work - meaning os.MkdirAll is idempotent.
My question is, is there a benefit of doing the os.Stat check? Is it a much lighter operation than os.MkdirAll?
The first thing MkdirAll does is call os.Stat to check if the path exists and is a directory.
func MkdirAll(path string, perm FileMode) error {
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
dir, err := Stat(path)
if err == nil {
if dir.IsDir() {
return nil
}
return &PathError{"mkdir", path, syscall.ENOTDIR}
}
...
From the docs:
If path is already a directory, MkdirAll does nothing and returns nil.
So no, you don't need to call os.Stat.

Resources