在尝试将一些bash脚本变成turtle时仍面临问题,null终止字符串尤其是罪魁祸首

时间:2016-07-23 19:35:13

标签: haskell-turtle

当试图将一些(对我来说)常见的bash成语变成乌龟脚本时, 我还是遇到问题。这是一篇很长的帖子,对不起 - 你可能只是跳过了 介绍性解释,并在最后跳到实际问题 - 但我希望以这种方式清楚地表达我的观点(问题)。

我经常在bash脚本中使用的一个成语是链接在一起(管道)find,egrep和xargs 使用以null结尾的字符串。原因很简单:即使是带有空格和其他奇怪的文件名 字符不会以这种方式引起任何问题。

我会用这样的东西:

找到。 -name" *" -print0 ... | egrep -z -Z ... | xargs -0 ...

有时我想在与-L 1

匹配的文件上逐行工作 找到。 -name" *" -print0 ... | egrep -z -Z ... | xargs -0 -L 1 ...

或者,而不是xargs -0 ...我会使用另一个工具,比如rssh和ssh, 也理解空终止字符串:-0

将当前目录的(基本)内容同步/保存到其他目录 例如。我会使用类似的东西:

binaries="exe$"
logfiles="log$"
pidfiles="pid$"
shakestuff="\_shake|\_build|\.\.database"
pat="^\.$|/dist|\.cabal-sandbox|cabal\.sandbox\.config|$shakestuff|\.o$|\.dyn_o$|\.hi$|\.dyn_hi$|\.hdevtools.sock$|$binaries|$logfiles|$pidfiles|TAGS"

find . -iname "*" -print0 -type f | egrep -z -Z -v "$pat" | rsync -a -e ssh --delete --progress --files-from=- -0 ./ .../path/to/some/other/dir
  • find打印当前目录中的所有文件,null终止:-print0

  • egrep -v" $ pat",从这个文件列表中只保留那些与模式$ pat不匹配的文件, 仅限基本文件即:我不打算在.cabal-sandbox中同步/保存文件 目录例如,并且位于该链中间的egrep必须消耗和生产 null终止字符串:-z -Z 图案pat预先组装在一起。

  • 这里指示使用ssh的rsync从stdin获取输入: - files-from = - , 再次null终止:-0(注意,虽然通常" rsync ... from到"表现 根据目录来自下面的斜杠,给出了非常不同的结果, 在这里:./或不,这里不太重要,因为rsync的输入来自stdin: - )

现在我试图把它变成一个乌龟脚本,虽然取得了一些成功,但是我仍然面对着 一些问题,并希望把它变成更惯用的海龟:

为了完整性,这是我目前在文件sync.hs中工作的脚本, 在一个小runturtle bash脚本的帮助下调用, 我可以调用sync.hs

  1. 要么只显示正在考虑的文件列表:sync.hs -e

  2. 或将它们同步到另一个目录,如:sync.hs --to / path / to / other / dir

  3. 这是代码(runturtle):

    #!/bin/sh
    exec cabal exec runhaskell -- "$@"
    

    这是代码(sync.hs):

    #!/usr/bin/env runturtle
    
    {-# LANGUAGE OverloadedStrings #-}
    
    -- {-# LANGUAGE ExtendedDefaultRules #-}
    
    {-# OPTIONS_GHC -fno-warn-type-defaults #-}
    
    
    import Turtle
    
    
    data Opts = Opts {
      doEcho :: Bool
      , toDir :: Turtle.FilePath
      }
      deriving (Show)
    
    parser :: Parser Opts
    parser = Opts <$>
         (switch "echo" 'e' "echo the files considered for synchronizing")
         <*> (optPath "to" 't' "sync to dir")
    
    binaries="|\\./website$|srv$"
    
    logfiles="|log$"
    
    pidfiles="|pid$|pnm$"
    
    shakestuff="|_shake|_build|\\.\\.database"
    
    pat="^\\.$"
      <>"|/dist|\\.cabal-sandbox|cabal\\.sandbox\\.config"
      <> shakestuff
      <>"|\\.git|\\.o$|\\.dyn_o$|\\.hi$|\\.dyn_hi$|\\.hdevtools.sock$"
      <> binaries
      <> logfiles
      <> pidfiles
      <>"|TAGS"
    
    sync :: Opts -> IO ()
    sync opts = do {
    
      ; echo "syncing..."
      ; when (doEcho opts)
    (do {
        ; echo $ "pat: " <> pat
    
        ; sh $ do inproc  "find" [".", "-iname", "*", "-print0", "-type", "f"] empty 
            & inproc "egrep" ["-z", "-Z" , "-v", pat]
            & inproc "xargs" ["-0", "-L", "1"]
            & grep (has ".")
            >>= echo
        ; exit ExitSuccess
        })
    
    
    
    
      ; do {
      ; let txt = "find . -iname \"*\" -print0 -type f | egrep -z -Z -v \"" <> pat <>"\" | rsync -a -e ssh --delete  --progress --files-from=- -0 ./ "
              <> format fp (toDir opts)
      ; echo txt
      ; shell txt empty
      ; return ()
      }
    
    
      ; return ()
    
      }                                      
    
    
    
    main :: IO ()
    main = (do {
           ; opts <- options "sync file to another directory" parser
           ; print (opts)
           ; sync opts
           ; return ()
    
           })
    

    现在这是我对这个脚本的问题:

    首先:我可以在命令行上运行它,我的flycheck语法检查 在emacs依赖ghc其他hdevtools工作正常,从而获得 现在,Haskell的强大打字功能可以为shell编写好处(感谢创建龟 顺便说说)。我甚至可以在命令行上使用乌龟(cabal repl)

    cabal repl
    > :set -XOverloadedStrings
    > import Turtle
    > ls "."
    > view (shell "whatever cmd" empty)
    

    等,但是如果我加载了我的sync.hs脚本,我就无法访问它的各个部分(函数 同步定义)

    > :l sync.hs 
    [1 of 1] Compiling Main             ( sync.hs, interpreted )
    Ok, modules loaded: Main.
    

    我希望看到上面定义的模式,例如:

    > pat
    
    <interactive>:12:1:
    Not in scope: ‘pat’
    Perhaps you meant ‘cat’ (imported from Turtle)
    

    我想使用sync.hs中定义的函数作为实验的快捷方式 例如。像这样

    > view $ inproc "find" [".", "-iname", "*", "-print0", "-type", "f"] empty & inproc "egrep" ["-z", "-Z" , "-v", pat]
    
    <interactive>:15:111:
    Not in scope: ‘pat’
    Perhaps you meant ‘cat’ (imported from Turtle)
    

    其次,你可能已经注意到我在上面的乌龟脚本中已经使用过&#34;更多惯用的&#34; 在回声的情况下龟:

    ; sh $ do inproc  "find" [".", "-iname", "*", "-print0", "-type", "f"] empty 
        & inproc "egrep" ["-z", "-Z" , "-v", pat]
        & inproc "xargs" ["-0", "-L", "1"]
        & grep (has ".")
        >>= echo
    

    即。我正在使用乌龟风格的管道:功能应用,这里的顺序与&amp ;, 至少比toDir更真实,我实际上依赖于bash 做这个工作:

    ; let txt = "find . -iname \"*\" -print0 -type f | egrep -z -Z -v \"" <> pat <>"\" | rsync -a -e ssh --delete  --progress --files-from=- -0 ./ "
        <> format fp (toDir opts)
    ; echo txt
    ; shell txt empty
    

    但即使在这个更为惯用的回声案例中,我也不得不采取一些解决方法:grep(有&#34;。&#34;),如果我不使用它,我会看到空字符串:

    turtle> view $ inproc "find" [".", "-iname", "*", "-print0", "-type", "f"] empty & inproc "egrep" ["-z", "-Z" , "-v", "\\.cabal-sandbox|/dist"]
    

    输出(这里省略了很多输出,但是看到单个&#34; \ NUL&#34;在最后):

    "...ntax.hs\NUL./static/lib-pi-forall/src/PiForall/Parser.hs\NUL./static/lib-pi-forall/src/PiForall/TypeCheck.hs\NUL./static/lib-pi-forall/LICENSE\NUL./shclean.do\NUL./TAGS\NUL./T10.hs\NUL./todo-yet-stop-the-program-as-in-running-if-not-told-another\NUL./talks\NUL./index.html\NUL./T1.hs.orig\NUL./sbbuild.sh\NUL./_shake\NUL./_shake/Main.hi\NUL./_shake/Main.dyn_o\NUL./_shake/build\NUL./_shake/Main.o\NUL./_shake/Main.dyn_hi\NUL./T4.hs\NUL./sync.hs\NUL./etc\NUL./.hdevtools.sock\NUL./more-stuff.hs\NUL./my.hs\NUL./T9.hs\NUL./snap-index\NUL./T6.hs\NUL./etc.html\NUL./cabalfile.hs\NUL./todo-maybe-issue-start-stop-restart-july2016\NUL./try-turtle-urwclassico.do\NUL./install.do\NUL./update-rc\NUL./index\NUL./done-pipe\NUL./clean.do\NUL./bootstrap.do\NUL./mystuff.cabal\NUL./pire\NUL./log\NUL./build.sh\NUL./goodsync.hs\NUL./cmds.hs\NUL./LICENSE\NUL./dry.do\NUL./T5.hs\NUL./snap-pire\NUL"
    "\NUL"
    

    如果我不愿意用grep删除它们,请查看我最后得到的空字符串(有&#34;。&#34;)

    turtle> view $ inproc "find" [".", "-iname", "*", "-print0", "-type", "f"] empty & inproc "egrep" ["-z", "-Z" , "-v", "\\.cabal-sandbox|/dist"] & inproc "xargs" ["-0", "-L", "1"]
    
    (again lots of output omitted)
    "./done-pipe"
    "./clean.do"
    "./bootstrap.do"
    "./mystuff.cabal"
    "./pire"
    "./log"
    "./build.sh"
    "./goodsync.hs"
    "./cmds.hs"
    "./LICENSE"
    "./dry.do"
    "./T5.hs"
    "./snap-pire"
    ""
    ""
    ""
    ""
    turtle> 
    

    这是为什么?在bash我不必这样做!任何更好/推荐使用null终止的方法 龟中的字符串?

    最后,并非最不重要的是,我无法为另一方提出惯用的海龟解决方案, rsync一段代码。这是一次尝试,但看看会发生什么:一些文件被转移, 但rsync抱怨我当前的dir / home / rx / work / servant /未找到null终止: link_stat&#34; / home / rx / work / servant /#012&#34;失败: (是的:它的名字只是&#34; / home / rx / work / servant /&#34; not&#34; / home / rx / work / servant /#012&#34;)

    ; view $ inproc "find" [".", "-iname", "*", "-print0", "-type", "f"] empty 
        & inproc "egrep" ["-z", "-Z", "-v", pat]
        & grep (has ".")
        & shell ("rsync -a -e ssh --delete --progress --files-from=- -0 ./ " <> (format fp $ toDir opts))
    
    
    rx@softland ~/work/servant $ ./sync.hs --to ~/tmp/website_
    Opts {doEcho = False, toDir = FilePath "/home/rx/tmp/website_"}
    syncing...
    building file list ... 
    rsync: link_stat "/home/rx/work/servant/\#012" failed: No such file or directory (2)
    135 files to consider
    ./
    q
          8,715 100%    0.00kB/s    0:00:00 (xfr#1, to-chk=95/135)
    sync.hs
          2,034 100%    1.94MB/s    0:00:00 (xfr#2, to-chk=86/135)
    rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1183) [sender=3.1.1]
    ExitFailure 23
    rx@softland ~/work/servant $
    

    但实际上我甚至想使用inproc作为rsync片段(有或没有grep(有&#34;。&#34;))

    ; view $ inproc "find" [".", "-iname", "*", "-print0", "-type", "f"] empty 
      & inproc "egrep" ["-z", "-Z", "-v", pat]
      & grep (has ".")
      & inproc "rsync" ["-a", "-e", "ssh", "--delete", "--progress", "--files-from=-", "-0", "./", format fp $ toDir opts]
    
    
    
    rx@softland ~/work/servant $ ./sync.hs --to ~/tmp/website_
    Opts {doEcho = False, toDir = FilePath "/home/rx/tmp/website_"}
    syncing...
    "building file list ... "
    rsync: link_stat "/home/rx/work/servant/\#012" failed: No such file or directory (2)
    " 0 files...\r 100 files...\r137 files to consider"
    "./"
    "sync.hs"
    "\r          2,053 100%    0.00kB/s    0:00:00  \r          2,053 100%    0.00kB/s    0:00:00 (xfr#1, to-chk=86/137)"
    rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1183) [sender=3.1.1]
    rx@softland ~/work/servant $
    

    提前致谢。

0 个答案:

没有答案