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

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

  •  
  •   CatCode · 31 天前 · 5577 次点击
    这是一个创建于 31 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    # 危险命令请勿模仿
    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   31 天前
    楼主不先试试 find ./ -type d -print0 -name '.git' 出来的是什么?
    echo1937
        2
    echo1937   31 天前   ❤️ 1
    我试验了一下,
    find ./ -type d -print0 -name '.git' 似乎真正的左右是 find ./ -type d -print0
    find ./ -type d -name '.git' 才是查找.git 的目录

    问题应该在这里.
    3gs
        3
    3gs   31 天前   ❤️ 1
    我猜 -print0 后面的参数会被忽略,应该放后边
    larisboy
        4
    larisboy   31 天前   ❤️ 1
    find path -option [ -print ] [ -exec -ok command ] {} \;


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

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

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

    是 find 的参数有顺序,不是 xargs
    tlday
        21
    tlday   31 天前
    并不只是 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   31 天前
    @reus #8 其实是因为 find 是一个不完整的指令式编程语言
    请把 “垃圾设计” 引申到一切指令式编程语言,我会表示完全同意。单指 find,我觉得不行。
    wdidwlia
        23
    wdidwlia   31 天前 via iPhone
    取决于用哪个 shell, 其实 rm 一条命令也能解决
    reus
        24
    reus   31 天前
    @no1xsyzy 一个命令做好自己的事情,要复杂的控制指令,让 shell 来做,就行了。find 又有 exec 又有 delete 等等根本不需要的东西,又各种随意堆砌的参数规则。sed 也有语言,awk 也有语言,但都不像 find 这样残疾,我是不会引申的。糟粕就是糟粕。

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

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