kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -24- <Remove,RemoveAll,Rename,SameFile>

こんにちは、kurumi-bioです。 第10回目のosパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.1 linux/amd64

Remove関数

func Remove(name string) error

関数の説明Remove は、指定されたファイルまたは (空の) ディレクトリを削除します。エラーがある場合、タイプは *PathError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rm(fileName string) {
    e := os.Remove(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Remove", e))
        return
    }
    fmt.Printf("[%s] Remove Success\n", fileName)
}

func main() {
    const Name = "test"
    SubPath := fmt.Sprintf("%s/sub", Name)
    rm(Name)
    os.Mkdir(Name, 0750)
    rm(Name)
    os.MkdirAll(SubPath, 0750)
    rm(Name)
    rm(SubPath)
    rm(Name)
}

コードの説明 プライベートのrm関数でos.Removeを実行しています。削除できたら"Remove Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、対象ファイルが存在しなかった場合、対象フォルダが存在した場合、対象フォルダが空ではなかった場合の動きを調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:testが存在しないためThe system cannot find the file specified.(指定されたファイルが見つかりません)というエラーが出力されました。
  • 2行目:testディレクトリを作成後にos.Removeを実行しているため"Remove Success"と出力されました。
  • 3行目:test/subディレクトリを作成後にos.Removeを実行したので、"test"ディレクトリは"sub"デレクトリが存在しThe directory is not empty.(ディレクトリが空ではありません)というエラーが出力されました。
  • 4行目:"test/sub"を引数にos.Removeを実行したため、"sub"ディレクトリが空なので"Remove Success"と出力されました。
  • 5行目:4行目で"sub"ディレクトリを削除したので、testディレクトリが空ディレクトリとなり"Remove Success"と出力されました。

RemoveAll関数

func RemoveAll(path string) error

関数の説明RemoveAll は、パスとそれに含まれるすべての子を削除します。削除できるものはすべて削除しますが、最初に遭遇したエラーを返します。パスが存在しない場合、RemoveAll は nil (エラーなし) を返します。エラーがある場合、タイプは *PathError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rma(fileName string) {
    e := os.RemoveAll(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Remove", e))
        return
    }
    fmt.Printf("[%s] Remove Success\n", fileName)
}

func main() {
    const Name = "test"
    SubPath := fmt.Sprintf("%s/sub", Name)
    rma(Name)
    os.Mkdir(Name, 0750)
    rma(Name)
    os.MkdirAll(SubPath, 0750)
    rma(Name)
}

コードの説明 プライベートのrma関数でos.RemoveAllを実行しています。削除できたら"Remove Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、対象ファイルが存在しなかった場合、対象フォルダが存在した場合、対象フォルダが空ではなかった場合の動きを調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:存在しないtestディレクトリを指定しos.RemoveAllを実行し"Remove Success"と出力されました。
  • 2行目:testディレクトリを作成後にos.RemoveAllを実行し"Remove Success"と出力されました。
  • 3行目:test/subディレクトリを作成後にos.RemoveAllを実行し"Remove Success"と出力されました。

広告の下に続きます。

Rename関数

func Rename(oldpath, newpath string) error

関数の説明Rename は、oldpath を newpath に名前変更 (移動) します。 newpath が既に存在し、ディレクトリでない場合、Rename はそれを置き換えます。 oldpath と newpath が異なるディレクトリにある場合、OS 固有の制限が適用される場合があります。同じディレクトリ内であっても、Unix 以外のプラットフォームでは、名前の変更はアトミック操作ではありません。エラーが発生した場合、タイプは *LinkError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rf(filename string) {
    b, e := os.ReadFile(filename)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.ReadFile", e))
        return
    }
    fmt.Printf("%s [%s]\n", filename, b)
}

func rn(oldpath, newpath string) {
    e := os.Rename(oldpath, newpath)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%s\n", os.NewSyscallError("os.Rename", e))
        return
    }
    fmt.Println("Rename Success")
}

func main() {
    rn("non", "non2")
    fmt.Println("----------")

    rf("test-old")
    rn("test-old", "test-new")
    rf("test-new")
    fmt.Println("----------")

    rf("test-new2")
    rn("test-new", "test-new2")
    rf("test-new2")
    fmt.Println("----------")

    rn("test-new2", "test-dir")
    fmt.Println("----------")

    rn("test-new2", "c:\\test-new")
    rn("test-new2", "d:\\test-new")
    fmt.Println("----------")

}

コードの説明 プライベートのrn関数でos.Renameを実行しています。名前変更できたら"Rename Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、元ファイル(oldpath)が存在しない場合、元ファイル(oldpath)が存在する場合、新ファイル(newpath)が存在する場合、新ファイル(newpath)がディレクトリとして存在する場合、ドライブをまたぐ場合の挙動を調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1ブロック目:元ファイルに存在しないファイル"non"を指定してos.Renameを実行したため、The system cannot find the file specified.(指定されたファイルが見つかりません)というエラーが出力されました。
  • 2ブロック目:os.RemoveAllで"test-old"ファイルを"test-new"ファイルに名前変更に成功しtest-newファイルの中身がtest-newファイルと同じことが確認できました。
  • 3ブロック目:os.RemoveAllで"test-old"ファイルを存在する"test-new2"ファイルに名前変更(置き換え)しました。test-newファイル2の中身がtest-newファイルと同じになることが確認できました。
  • 4ブロック目:新ファイルに存在するディレクトリを指定してos.Renameを実行したため、Access is denied.(アクセスが拒否)というエラーが出力されました。
  • 5ブロック目:Dドライブに存在するファイルをCドライブのファイルを指定してos.Renameを実行したため、Access is denied.(アクセスが拒否)というエラーが出力されました。
    Dドライブは同一どらいぶなので成功して"Rename Success"が出力されました。

SameFile関数

func SameFile(fi1, fi2 FileInfo) bool

関数の説明SameFile は、fi1 と fi2 が同じファイルを記述しているかどうかを報告します。たとえば、Unix では、これは、下にある 2 つの構造体のデバイス フィールドと inode フィールドが同一であることを意味します。他のシステムでは、決定はパス名に基づく場合があります。 SameFile は、このパッケージの Stat によって返される結果にのみ適用されます。それ以外の場合は false を返します。

◆テストコード

package main

import (
    "fmt"
    "io/fs"
    "os"
)

func fi(name string) fs.FileInfo {
    fi, e := os.Stat(name)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        os.Exit(1)

    }
    return fi
}

func sf(name1, name2 string) {
    fi1 := fi(name1)
    fi2 := fi(name2)

    b := os.SameFile(fi1, fi2)
    if b == true {
        fmt.Printf("[%s] = [%s]\n", name1, name2)
    } else {
        fmt.Printf("[%s] != [%s]\n", name1, name2)
    }
}

func main() {
    sf("same", "same")
    sf("same", "s-link")
    sf("same", "h-link")
    sf("same", "same1")
}

コードの説明 プライベートのsf関数でos.SameFileを実行しています。同一ファイルの場合は"="を出力し、異なる場合は"!="を出力します。
この関数は、main()関数内で呼ばれており、同一ファイル、シンボリックリンク、ハードリンク、別ファイルの挙動を調べるプログラムになっています。

◆実行結果(Windows)

実行環境の説明 s-linkファイルは、sameファイルのシンボリックリンク
h-linkファイルは、sameファイルのハードリンク
same1ファイルは、sameファイルと別ファイル
になっています。

実行結果の説明

  • 1行目:同じ名前(ファイル)を指定しos.SameFileを実行したため"="が出力されました。
  • 2行目:シンボリックファイルの名前を指定しos.SameFileを実行したため"="が出力されました。
  • 3行目:ハードリンクファイルの名前を指定しos.SameFileを実行したため"="が出力されました。
  • 4行目:異なる名前(ファイル)を指定しos.SameFileを実行したため"!="が出力されました。

最後までご覧いただきありがとうございます