在Golang中引用一个文件并在每行前运行一个命令。

huangapple go评论115阅读模式
英文:

Source a file inside golang and run a command before each listed line

问题

在一个golang程序中,我想要引用一个文件(在这种情况下是.clean),它的内容如下:

  1. $HOME/directory1
  2. $HOME/directory1/.directory2
  3. $HOME/directory3

然后在每个目录之前运行rm -rf命令。有人知道如何实现这个吗?

英文:

Inside a golang program i want to source a file (in this case its .clean) which would look like this

  1. $HOME/directory1
  2. $HOME/directory1/.directory2
  3. $HOME/directory3

and then run the rm -rf command before each directory.
Does anyone know how to accomplish this?

答案1

得分: 3

你可以使用bufio.Scanner来实现这个功能。

我添加了粗体文本

> Scanner提供了一个方便的接口,用于读取数据,例如由换行符分隔的文本行文件。连续调用Scan方法将逐步遍历文件的“标记”,跳过标记之间的字节。标记的定义由类型为SplitFunc的拆分函数定义;默认的拆分函数将输入拆分为去除行终止符的行。此包中定义了用于将文件扫描为行、字节、UTF-8编码的符文和以空格分隔的单词的拆分函数。客户端也可以提供自定义的拆分函数。

使用os.RemoveAll()的示例:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. func main() {
  9. f, err := os.Open(".clean")
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. s := bufio.NewScanner(f)
  14. for s.Scan() {
  15. fmt.Println("Deleting:", s.Text())
  16. if err := os.RemoveAll(s.Text()); err != nil {
  17. log.Println(err)
  18. }
  19. }
  20. if err := s.Err(); err != nil {
  21. log.Fatal(err)
  22. }
  23. }

Playground

或者,使用os/exec中的Cmd.Run()运行rm -rf

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "os/exec"
  8. )
  9. func main() {
  10. f, err := os.Open("file.txt")
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. s := bufio.NewScanner(f)
  15. for s.Scan() {
  16. fmt.Println("Deleting:", s.Text())
  17. cmd := exec.Command("rm", "-rf", s.Text())
  18. if err := cmd.Run(); err != nil {
  19. log.Println(err)
  20. }
  21. }
  22. if err := s.Err(); err != nil {
  23. log.Fatal(err)
  24. }
  25. }

Playground

英文:

You can do this using a bufio.Scanner.

Bold text added by me.

>Scanner provides a convenient interface for reading data such as a file of newline-delimited lines of text. Successive calls to the Scan method will step through the 'tokens' of a file, skipping the bytes between the tokens. The specification of a token is defined by a split function of type SplitFunc; the default split function breaks the input into lines with line termination stripped. Split functions are defined in this package for scanning a file into lines, bytes, UTF-8-encoded runes, and space-delimited words. The client may instead provide a custom split function.

Example using os.RemoveAll():

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. func main() {
  9. f, err := os.Open(".clean")
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. s := bufio.NewScanner(f)
  14. for s.Scan() {
  15. fmt.Println("Deleting:", s.Text())
  16. if err := os.RemoveAll(s.Text()); err != nil {
  17. log.Println(err)
  18. }
  19. }
  20. if err := s.Err(); err != nil {
  21. log.Fatal(err)
  22. }
  23. }

Playground

Or, using Cmd.Run() from os/exec to run rm -rf:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "os/exec"
  8. )
  9. func main() {
  10. f, err := os.Open("file.txt")
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. s := bufio.NewScanner(f)
  15. for s.Scan() {
  16. fmt.Println("Deleting:", s.Text())
  17. cmd := exec.Command("rm", "-rf", s.Text())
  18. if err := cmd.Run(); err != nil {
  19. log.Println(err)
  20. }
  21. }
  22. if err := s.Err(); err != nil {
  23. log.Fatal(err)
  24. }
  25. }

Playground

答案2

得分: 0

而不是“引用”文件,你可以直接读取它:

  1. while IFS= read TARGET; do
  2. rm -fr "${TARGET/'$HOME'/$HOME}"
  3. done < .clean

你还可以添加一些检查,比如跳过注释:

  1. while read TARGET; do ## 显式地不更改 IFS 以排除前导和尾随空格。
  2. case "$TARGET" in
  3. \#*)
  4. # 跳过注释。
  5. ;;
  6. *)
  7. rm -fr "${TARGET/'$HOME'/$HOME}"
  8. ;;
  9. esac
  10. done < .clean

如果你需要更多的兼容性,即它不支持 ${PARAM/X/Y} 扩展方法,仍然可以使用 sed:

  1. rm -fr "$(echo "$TARGET" | sed "s|$HOME|$HOME|")" ## 没有 'g'。我怀疑有两个 `$HOME` 是不明智的。
英文:

Instead of "sourcing" the file, you could instead just read it:

  1. while IFS= read TARGET; do
  2. rm -fr &quot;${TARGET/&#39;$HOME&#39;/$HOME}&quot;
  3. done &lt; .clean

You can also add checks to it like skipping comments:

  1. while read TARGET; do ## Explicitly do not change IFS to exclude leading and trailing spaces.
  2. case &quot;$TARGET&quot; in
  3. \#*)
  4. # Skip comments.
  5. ;;
  6. *)
  7. rm -fr &quot;${TARGET/&#39;$HOME&#39;/$HOME}&quot;
  8. ;;
  9. esac
  10. done &lt; .clean

If you need more compatibility i.e. it doesn't support ${PARAM/X/Y} expansion method, just used sed anyway:

  1. rm -fr &quot;$(echo &quot;$TARGET&quot; | sed &quot;s|$HOME|$HOME|&quot;)&quot; ## No &#39;g&#39;. I doubt it&#39;s sensible to have two `$HOME`&#39;s.

huangapple
  • 本文由 发表于 2014年6月4日 19:48:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/24036583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定