V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
CatCode
V2EX  ›  Linux

老哥们,为什么我这行命令就删库了啊!求助

  •  
  •   CatCode · 2020-07-15 10:04:44 +08:00 · 7171 次点击
    这是一个创建于 1590 天前的主题,其中的信息可能已经有所发展或是发生改变。

    命令如下:(危险命令请勿模仿

    # 危险命令请勿模仿
    find ./ -type d -print0 -name '.git' | xargs -0 -s1024 /bin/rm -rf
    

    危险命令请勿模仿

    原本的想法:这个目录是别的 git 库 clone 过来的,因为所有必要的文件都已经 checkout 出来了。为了在后面遍历文件的步骤中,减少遍历到不必要的文件,于是打算删掉所有名为.git的目录。

    然而,当我运行了这个命令,本目录下所有的子目录都被删除了。我就懵逼了,为啥?

    33 条回复    2020-07-26 21:42:05 +08:00
    larisboy
        1
    larisboy  
       2020-07-15 10:11:31 +08:00
    楼主不先试试 find ./ -type d -print0 -name '.git' 出来的是什么?
    echo1937
        2
    echo1937  
       2020-07-15 10:13:16 +08:00   ❤️ 1
    我试验了一下,
    find ./ -type d -print0 -name '.git' 似乎真正的左右是 find ./ -type d -print0
    find ./ -type d -name '.git' 才是查找.git 的目录

    问题应该在这里.
    3gs
        3
    3gs  
       2020-07-15 10:15:18 +08:00   ❤️ 1
    我猜 -print0 后面的参数会被忽略,应该放后边
    larisboy
        4
    larisboy  
       2020-07-15 10:16:21 +08:00   ❤️ 1
    find path -option [ -print ] [ -exec -ok command ] {} \;


    -print 应该 option 后面
    guanhui07
        5
    guanhui07  
       2020-07-15 10:19:03 +08:00
    还是要谨慎些 打印出来看看啥
    dalidali
        6
    dalidali  
       2020-07-15 10:21:06 +08:00   ❤️ 1
    老哥 艺高人胆大啊
    CatCode
        7
    CatCode  
    OP
       2020-07-15 10:21:21 +08:00
    感谢各位,我重新 clone 了,把-print0 放后面就好了
    我才知道 xargs 的参数是有先后顺序的
    reus
        8
    reus  
       2020-07-15 10:21:56 +08:00
    前几天还有个头条面试官非要说 find 才是正确答案来着?

    find 这种上古东西还是算球了,参数位置影响输出的,垃圾设计。
    sonice
        9
    sonice  
       2020-07-15 10:24:39 +08:00
    @reus 麻烦给个现代一点的命令让我开开眼界
    DJQTDJ
        10
    DJQTDJ  
       2020-07-15 10:27:43 +08:00
    $ find . -name '*.bak' -print0 | xargs -0 rm

    艺高人胆大。
    defunct9
        11
    defunct9  
       2020-07-15 10:27:44 +08:00
    rust 的 fd
    tankren
        12
    tankren  
       2020-07-15 10:33:07 +08:00
    为什么上来就要用组合命令呢 不应该先看看前面返回了啥?
    felixcode
        13
    felixcode  
       2020-07-15 10:47:20 +08:00
    find 我通常用-exec 来做,貌似好控制一些,还可以先不加-exec 查看一下。
    lovecy
        14
    lovecy  
       2020-07-15 10:48:30 +08:00
    这种操作,运行前打印出来检查下先。。
    当然最好还是先统一挪动到备份文件夹,然后一起删除
    securityCoding
        15
    securityCoding  
       2020-07-15 10:50:16 +08:00
    牛批牛批
    xuanbg
        16
    xuanbg  
       2020-07-15 10:50:38 +08:00
    git 本地库删掉没事,再 clone 一次就好了。远程库删掉也没啥,再推送上去就完了。
    reus
        17
    reus  
       2020-07-15 10:54:28 +08:00
    whasyt
        18
    whasyt  
       2020-07-15 11:19:06 +08:00
    find ./ -type d -name '.git' |xargs rm -rf
    huangmingyou
        19
    huangmingyou  
       2020-07-15 11:41:16 +08:00
    find > log.txt ; 这样会安全点。
    ETiV
        20
    ETiV  
       2020-07-15 11:43:37 +08:00 via iPhone
    @CatCode

    是 find 的参数有顺序,不是 xargs
    tlday
        21
    tlday  
       2020-07-15 12:49:00 +08:00
    并不只是 print 位置不对的问题,你如果执行 find ./ -type d -print -name '.git' -exec echo Matched {} \+ 就会有所发现。
    因为上面这条命令等价于 find ./ \( -type d -and -print -and -name '.git' \) -exec echo Matched {} \+

    而在-print 的文档中就说明了,这个“条件”总是为 true,并打印“当前”文件的 pathname 到 stdout 。( This primary always evaluates to true. It prints the pathname of the current file to standard output.)

    不知道为什么楼主会去单用 print 这个选项。因为 print 这个选项还说:假如"-exec, -ls, -print, -print0, -ok"没有任何一个被使用,那么命令会默认最后加一个-print ( If none of -exec, -ls, -print, -print0, or -ok is specified, the given expression shall be effectively replaced by ( given expression ) -print.)

    说 find 是上古东西的当然可以自己写脚本来做嘛,python 一个 os.walk 也不费什么劲。像 find 这种东西一些过时设计已经没法改了,因为肯定有大量的运维脚本依赖于这个“错误”设计。但是对于熟悉的人来说,写这么一段命令肯定比写脚本快得多。
    no1xsyzy
        22
    no1xsyzy  
       2020-07-15 13:18:00 +08:00
    @reus #8 其实是因为 find 是一个不完整的指令式编程语言
    请把 “垃圾设计” 引申到一切指令式编程语言,我会表示完全同意。单指 find,我觉得不行。
    wdidwlia
        23
    wdidwlia  
       2020-07-15 13:25:51 +08:00 via iPhone
    取决于用哪个 shell, 其实 rm 一条命令也能解决
    reus
        24
    reus  
       2020-07-15 14:09:01 +08:00
    @no1xsyzy 一个命令做好自己的事情,要复杂的控制指令,让 shell 来做,就行了。find 又有 exec 又有 delete 等等根本不需要的东西,又各种随意堆砌的参数规则。sed 也有语言,awk 也有语言,但都不像 find 这样残疾,我是不会引申的。糟粕就是糟粕。

    稍微没那么上古的,看看 plan9 怎么做的吧: https://github.com/google/walk
    分开两个命令,一个做遍历一个做过滤,不比 find 好?
    Linco
        25
    Linco  
       2020-07-15 14:46:18 +08:00
    敢把 rm -rf 放到管道后面的都是狠人
    no1xsyzy
        26
    no1xsyzy  
       2020-07-15 15:10:57 +08:00
    @reus #24 还不是因为管道得走一遍内核,而且 sor 反复 fork/exec 无数遍切换(我也想不通为什么要当作 bash 而不是),多花的时间长得可怕。分命令通常是不太可行的。
    残缺倒是真的,前些天碰到什么我甚至记不得是啥情况的边角问题,查了一圈发现只能返回到 shell 再处理。
    大概重新做个语法好点的倒是有用,不过不如自己写脚本了。
    可能 pwsh 有奇效……
    no1xsyzy
        27
    no1xsyzy  
       2020-07-15 15:14:43 +08:00
    @reus #24 残缺归残缺,别把问题丢 “参数位置影响输出” 上…… 至于又想做些复杂功能又做得残缺,git 不也是这样么……
    @tlday #21 看了下,因为是 -print0,采用 '\0' 断而不是 LF 断,后面 xargs 也是 -0,这样可以避免文件名带换行导致错误
    pouta
        28
    pouta  
       2020-07-15 15:17:43 +08:00
    666
    Mutoo
        29
    Mutoo  
       2020-07-15 15:20:39 +08:00
    reus
        30
    reus  
       2020-07-15 15:41:23 +08:00
    @no1xsyzy 问题就是参数位置影响输出,为什么你总是要否定问题所在?

    git 也是这样? git 的命令很明确分成 plumbing 和 porcelain 两类,高层命令做不了的事情,那就用底层命令自己搭。拿 git 和 find 比?搞笑过头了。
    no1xsyzy
        31
    no1xsyzy  
       2020-07-15 16:02:35 +08:00
    @reus #30 明明问题出在 Unix 哲学本身上,为什么要怪罪于一个 (1) 的工具?
    因为 Unix 哲学深植于 worse is better,导致一堆程序需要自己实现大部分 performance-oriented workaround
    这不是一样的么……
    maxbon
        32
    maxbon  
       2020-07-18 16:30:54 +08:00
    勇士,就跟 rm -fr +相对路径一样。rm -fr ../../ ,这种我都不敢用的,一不小心就 GG 了
    movsb
        33
    movsb  
       2020-07-26 21:42:05 +08:00
    find 的表达式是从左往右执行的,其中一个表达式返回 true 后面的就不执行了,-print0 始终返回 true 。所以,结果你知道了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1173 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:11 · PVG 02:11 · LAX 10:11 · JFK 13:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.