How to sort file names with Go Programming Language? - go

In my Go project, I need to sort the .json files and to display their name on the terminal when I'm running this command on the terminal go run main.go.
I coded a program which displays all the files in the folder, but I need to sort the .json file.
My code is the following :
package main
import (
"fmt"
"log"
"os"
"bytes"
"io"
)
func main() {
if os.Args[1] == "display-json-name" {
//reads the directory name and returns a list of directory entries
dirname := "."
f, err := os.Open(dirname)
if err != nil {
log.Fatal(err)
}
files, err := f.Readdir(-1)
f.Close()
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
}
How can we sort just the different .json files?
And the hierarchy of my project is :

Based on comments, it appears that the question is "How to print files where the file has a .json extension". Here's the code:
if os.Args[1] == "display-json-name" {
//reads the directory name and returns a list of directory entries
dirname := "."
f, err := os.Open(dirname)
if err != nil {
log.Fatal(err)
}
files, err := f.Readdir(-1)
f.Close()
if err != nil {
log.Fatal(err)
}
for _, file := range files {
if filepath.Ext(file.Name()) == ".json" {
fmt.Println(file.Name())
}
}
}

https://golang.org/pkg/io/ioutil/#ReadDir
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
files, err := ioutil.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
}

Related

Golang - Zip a directory which includes empty subdirectory and files

I am trying to zip an existing directory that has some empty subdirectories as well.
Here is the folder structure.
parent/
├── child
│   └── child.txt
├── empty-folder
└── parent.txt
2 directories, 2 files
Here is the source code. It writes all the subdirectories which have files on that. But it skipped an empty subdirectory. Is there any way to add an empty subdirectory as well in the zip file?. Thanks in advance.
package main
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
)
// check for error and stop the execution
func checkForError(err error) {
if err != nil {
fmt.Println("Error - ", err)
os.Exit(1)
}
}
const (
ZIP_FILE_NAME = "example.zip"
MAIN_FOLDER_NAME = "parent"
)
// Main function
func main() {
var targetFilePaths []string
// get filepaths in all folders
err := filepath.Walk(MAIN_FOLDER_NAME, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
// add all the file paths to slice
targetFilePaths = append(targetFilePaths, path)
return nil
})
checkForError(err)
// zip file logic starts here
ZipFile, err := os.Create(ZIP_FILE_NAME)
checkForError(err)
defer ZipFile.Close()
zipWriter := zip.NewWriter(ZipFile)
defer zipWriter.Close()
for _, targetFilePath := range targetFilePaths {
file, err := os.Open(targetFilePath)
checkForError(err)
defer file.Close()
// create path in zip
w, err := zipWriter.Create(targetFilePath)
checkForError(err)
// write file to zip
_, err = io.Copy(w, file)
checkForError(err)
}
}
To write an empty directory you just need to call Create with the directory path with a trailing path separator.
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
const (
ZIP_FILE_NAME = "example.zip"
MAIN_FOLDER_NAME = "parent"
)
type fileMeta struct {
Path string
IsDir bool
}
func main() {
var files []fileMeta
err := filepath.Walk(MAIN_FOLDER_NAME, func(path string, info os.FileInfo, err error) error {
files = append(files, fileMeta{Path: path, IsDir: info.IsDir()})
return nil
})
if err != nil {
log.Fatalln(err)
}
z, err := os.Create(ZIP_FILE_NAME)
if err != nil {
log.Fatalln(err)
}
defer z.Close()
zw := zip.NewWriter(z)
defer zw.Close()
for _, f := range files {
path := f.Path
if f.IsDir {
path = fmt.Sprintf("%s%c", path, os.PathSeparator)
}
w, err := zw.Create(path)
if err != nil {
log.Fatalln(err)
}
if !f.IsDir {
file, err := os.Open(f.Path)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
if _, err = io.Copy(w, file); err != nil {
log.Fatalln(err)
}
}
}
}

How to append docx file in Golang

I want to copy all the contents of a docx file (including its formatting like bold, underline, bullets, paragraphs, etc.) and append it to another docx file.
In this case I want to copy contents from Source/D1.docx and append it to temp.docx
package main
import (
"io/ioutil"
"log"
"os"
)
func main() {
data, err := ioutil.ReadFile("./Source/D1.docx")
if err != nil {
log.Println(err)
}
file, err := os.OpenFile("temp.docx", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Println(err)
}
file.Write(data)
}
Do this:
git clone --depth 1 git://github.com/unidoc/unioffice
New-Item -ItemType Directory unioffice/document/merge
Set-Location unioffice/document/merge
git pull origin pull/448/head
Then in the merge folder, make this file:
package main
import (
"github.com/unidoc/unioffice/document"
"os"
"path/filepath"
)
func main() {
s := "TestDocument.docx"
doc0, e := document.Open(s)
if e != nil {
panic(e)
}
defer doc0.Close()
doc1, e := document.Open(s)
if e != nil {
panic(e)
}
defer doc1.Close()
doc0.AddParagraph().AddRun().AddPageBreak()
if e := doc0.Append(doc1); e != nil {
panic(e)
}
out := filepath.Join(os.TempDir(), "merged.docx")
doc0.SaveToFile(out)
}
Note this is just for testing, for real code you will want to get a license.
https://github.com/unidoc/unioffice

How to create new file using go script

I am new to go lang. I am able to create a new file from the terminal using go script. like this
go run ../myscript.go > ../filename.txt
but I want to create the file from the script.
package main
import "fmt"
func main() {
fmt.Println("Hello") > filename.txt
}
If you are trying to print some text to a file one way to do it is like below, however if the file already exists its contents will be lost:
package main
import (
"fmt"
"os"
)
func main() {
err := os.WriteFile("filename.txt", []byte("Hello"), 0755)
if err != nil {
fmt.Printf("Unable to write file: %v", err)
}
}
The following way will allow you to append to an existing file if it already exists, or creates a new file if it doesn't exist:
package main
import (
"os"
"log"
)
func main() {
// If the file doesn't exist, create it, or append to the file
f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
_, err = f.Write([]byte("Hello"))
if err != nil {
log.Fatal(err)
}
f.Close()
}
you just need to check the API documentation. This is one way to do it, there is others (with os or bufio)
package main
import (
"io/ioutil"
)
func main() {
// read the whole file at once
b, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
// write the whole body at once
err = ioutil.WriteFile("output.txt", b, 0644)
if err != nil {
panic(err)
}
}
Fprintln is pretty close to what you were trying to do:
package main
import (
"fmt"
"os"
)
func main() {
f, e := os.Create("filename.txt")
if e != nil {
panic(e)
}
defer f.Close()
fmt.Fprintln(f, "Hello")
}
https://golang.org/pkg/fmt#Fprintln

Golang find most recent file by date and time

I am not sure if I am doing this correctly, but ultimately I would like to find the most recent modified date of a file in a directory and return the file name. The code I have so far is as follows. Can someone please help me with a more efficient solution than this. I really have a feeling this is super hacky. What I am doing is getting the dates and removing the
package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
func main() {
dir := "C:\\temp\\"
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
fi, _ := os.Stat(dir + f.Name())
s := strings.Split(fi.ModTime().Format("2006-01-02 15.04.05.000"), " ")
fdate, err := strconv.Atoi(strings.Replace(s[0], "-", "", -1))
if err != nil {
fmt.Println(err)
}
ftime, err := strconv.Atoi(strings.Replace(s[1], ".", "", -1))
if err != nil {
fmt.Println(err)
}
fmt.Println(fi.Name(), fdate+ftime)
}
}
Pay attention to details and efficiency. Check for errors. You asked for files so skip directories and other things. Allow for multiple files with the same modified time stamp (for example, Windows file times have a resolution of, at best, 100-nanoseconds). You already have ModTime() so don't call os.Stat(). Use time.Time methods directly. And so on.
For example,
package main
import (
"fmt"
"io/ioutil"
"os"
"time"
)
func main() {
dir := `C:\temp\` // Windows directory
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
var modTime time.Time
var names []string
for _, fi := range files {
if fi.Mode().IsRegular() {
if !fi.ModTime().Before(modTime) {
if fi.ModTime().After(modTime) {
modTime = fi.ModTime()
names = names[:0]
}
names = append(names, fi.Name())
}
}
}
if len(names) > 0 {
fmt.Println(modTime, names)
}
}
You can just compare the outputs of fi.ModTime().Unix() and keep the largest value to find the most recently modified file.
For example:
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
dir := "/tmp/"
files, _ := ioutil.ReadDir(dir)
var newestFile string
var newestTime int64 = 0
for _, f := range files {
fi, err := os.Stat(dir + f.Name())
if err != nil {
fmt.Println(err)
}
currTime := fi.ModTime().Unix()
if currTime > newestTime {
newestTime = currTime
newestFile = f.Name()
}
}
fmt.Println(newestFile)
}

Why cant I open a text file when I use the wrong file extension while trying to open it?

I'm trying to read a .txt file using Go, but I keep getting told that the program cannot find the specified file, even when I use the complete path to it. However, the code I have has no problem reading .go files.
Help?
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
// Open an input file, exit on error.
inputFile, err := os.Open("main.go");
if err != nil {
log.Fatal("Error opening input file:", err)
}
defer inputFile.Close()
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(scanner.Err())
}
}
You can see where you are adding this snippet of code at the beginning of your main function:
http://play.golang.org/p/DqnivLi1Z2
cwd, err := os.Getwd()
if err != nil {
log.Fatal("os.Getwd ", err)
}
log.Println("Current Directory", cwd)
files, err := ioutil.ReadDir(cwd)
if err != nil {
log.Fatal("ioutil.ReadDir", err)
}
for idx, finfo := range files {
log.Println(idx, " ", finfo.Name)
}

Resources