K&

可递归

 

 

思维导图:递归部分

 

 

 

package Createfile

import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "time"
)

func cmddir(dir string)  {
    //创建文件夹命令
    cmd := exec.Command("mkdir",dir)
    if _,err := cmd.CombinedOutput();err !=nil{
        log.Println(err)
    }
}

func exist(dir string) {
    //检查文件/文件夹状态,go中如果文件/文件夹存在是不会判定为错误的所以err会为空
    f,err := os.Stat(dir)
    if err == nil{
        //判定是不是目录
        if f.IsDir(){
            //是,什么都不做就返回
            return
        }else{
            cmddir(dir)
        }
    }
    //err不为空如果isnotexist判定为真那么就是不存在
    if os.IsNotExist(err){
        cmddir(dir)
    }
}

func CreateFile(dir string) *os.File{
    exist(dir)
    //拼接日志文件文件名字
    osfile,err := os.OpenFile(dir + "/getUrl.log" + fmt.Sprintf("-%d-%d-%d.log",
        time.Now().Year(),
        time.Now().Month(),
        time.Now().Day(),
    ),os.O_CREATE|os.O_WRONLY|os.O_APPEND,0644)
    if err != nil{
        log.Println(err)
    }
    //返回文件指针因为写入后要关闭但是写入不在这个函数中,不关闭会存在资源泄露严重会导致宕机
    return osfile
}

 

 

 

package Readfile

import (
    "io/ioutil"
    "log"
)

func ReadFile(filename string) []byte {
    //很简单,读取文件内容并返回内容
    fileByte,fileErr := ioutil.ReadFile(filename)
    if fileErr != nil {
        log.Println(fileErr)
    }
    return fileByte
}

 

 

 

package Treelist

import (
    "fmt"
    "io/ioutil"
    "path"
)

//这个是存储文件路径的切片可以理解为一组路径集合
var FileSlice []string

func Recursion(dir string) {
    //读取目录并不包含子目录
    files, errRead := ioutil.ReadDir(dir)
    if errRead != nil {
        fmt.Println(errRead)
    }
  //把上面读取的files便利因为读取后是个切片,需要逐一判断,如果是目录就拼接路径后接着便利
    for _, file := range files {
        if file.IsDir() {
            filename := file.Name()
            path := dir + filename + "/"
      //递归
            Recursion(path)
        }else {
        //不是就读取文件名字包含后缀,然后拼接成路径存在最开始定义的切片中
            filename := path.Base(file.Name())
            pwd := dir + filename
            FileSlice = append(FileSlice, pwd)
        }
    }
}

 

 

 

package UrlGet

import (
    "fmt"
    "littletools/GetUrl/Createfile"
    . "littletools/GetUrl/Readfile"
    "log"
    "mvdan.cc/xurls/v2"
    "regexp"
)

func UrlGet(filename string) {
    file := Createfile.CreateFile("OutPut")
    defer file.Close()
  //获取url,获取的值是切片
    arrayByte := xurls.Relaxed().FindAll(ReadFile(filename), -1)
  //便利k是索引也就是第几个,v就是索要的url
    for k, v := range arrayByte {
      //https/http开头的留下
        if match,err := regexp.MatchString(`^(https://){1}|^(http://){1} `,string(v));match{
            if err!=nil{
                log.Println(err)
            }
      //根据上述条件继续判断如果是要去除的fqdn那么就跳过进行下一条的判断,否则就存到文件中
            if matchGov,errGov := regexp.MatchString(`(去除的fqdn){1}`,string(v));matchGov{
                if errGov != nil{
                    log.Println(errGov)
                }
                continue
            }
            file.WriteString(fmt.Sprintf(" %s %d %s\n",filename, k, v))
        }
    }
}

 

 

 

package main

import (
    "fmt"
    "littletools/GetUrl/Treelist"
    "littletools/GetUrl/UrlGet"
    "os"
    "sync"
)

//同样为了并发安全不然会出现没执行完毕就退出的问题
var wg sync.WaitGroup

//给写入文件加锁,不然会发生并发不安全
var lock sync.Mutex

func main()  {

    if arg_num := len(os.Args[1:]);arg_num < 1{
        fmt.Println("Waring:请输入路径的名称")
        return
    }
    for _, v := range os.Args[1:] {
        dir := v + "/"
        Treelist.Recursion(dir)
    }
    for _, v := range Treelist.FileSlice {
        wg.Add(1)
        go func(filepath string) {
            lock.Lock()
            defer wg.Done()
            defer lock.Unlock()
            UrlGet.UrlGet(filepath)
        }(v)
    }
  //等待所有线程结束后推出
    wg.Wait()
}

 

 

测试目录结构

 

 

 

删除正则二次筛选结果会包含不要的正则部分

 

加上二次筛选结果不会包含不要的正则部分

 

 

 

 

纯个人手写思维,转载请注明出处,感谢。

我同意我亦师亦友的话,凭什么,别人十几年的积累你一招就能学会。所以我希望踏实的人能看我的博客有收获,同和我一样的小白一起进步,GO长期不定时更新。

 

一个不聪明的话痨运维(~^o^~)

posted on 2022-01-02 13:16  K&  阅读(116)  评论(0编辑  收藏  举报