パスワードを忘れた? アカウント作成
13557024 journal
日記

nemui4の日記: 本当にあった find コマンドの怖い話 26

日記 by nemui4

というのがはてな界隈にあるらしいのであとで見に行く予定は未定

この議論は、nemui4 (20313)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • by nemui4 (20313) on 2018年03月22日 8時08分 (#3380002) 日記

    【謎】本当にあったfindコマンドの怖い話【おもしろ現象】
    http://www.kunst1080.net/entry/2018/03/20/120146 [kunst1080.net]

    要約
    100万個のファイルに対して、find コマンドから始めて mv コマンドでファイル名を変更するワンライナーを実行すると、 mv コマンドが約158万回実行されました。

    ワンライナーでやろうとしてハマった?

    • by manmos (29892) on 2018年03月22日 10時15分 (#3380072) 日記

      findを実行した時点でのファイルだけをmvしたかったのに、mvされたあとのファイルもfindに引っかかってしまった。
      って、よくあるお話。

      当然やんとしか思わない。

      親コメント
      • by nemui4 (20313) on 2018年03月22日 10時44分 (#3380100) 日記

        なるほど、そういうもんなんすね。
        findはファイルのオーナー変更か古いファイルを削除するときに使うくらいでmvってやったことなかったです。
        どっちも
        ワンライナーにもこだわらないので、一旦リストファイルを生成してそれで次の処理をすることも多い。
        #賢いワンライナーを書ける技量が無い・・・だけか

        親コメント
        • by manmos (29892) on 2018年03月22日 11時09分 (#3380127) 日記

          私は一番使うのはfind - grepですね。

          #makefileには find . -type f -name '*~' -print0 | xargs -0 rm -fはかかれてて、よく使うけど。

          ;で区切って1lineでやるもよし。(shellのヒストリのため)

          親コメント
          • 私も一番よく使うのはgrepですが、
            % find . なんやかんか -print | xargs grep 条件1 | less

            % find . なんやかんか -print | xargs grep -l 条件1 | xargs grep 条件2 | less

            と、どんどん絞り込むことが多いです。-0をつけなくても大丈夫な状況限定。

            あと、ファイルそのものに何か手を入れる場合は、そのままxargsで繋がずに、

            % foreach f ( `find . なんやかんか -print | xargs grep -l 条件1 | xargs grep -l 条件2` )
            > perl -i.bak -pe ワンライナー $f
            > end

            って感じで、対象ファイル一覧を確定させてからコマンド実行してますね。
            今となってはなぜそうすることにしたのかぜんぜん覚えてないんですが、たぶん今回のネタのような何か痛い目にあったことがあったんだと思う。

            親コメント
            • by manmos (29892) on 2018年03月22日 17時12分 (#3380419) 日記

              そういえば、grepの-lに--print0とかほしいなぁ。macosとか最近めんどさいファイル名多いし。

              親コメント
              • by nemui4 (20313) on 2018年03月22日 17時25分 (#3380434) 日記

                grep で "-l" なんて使ったことがなかった(存在知らなかった)

                へー、含まれていないファイルを探すんですね。
                ファイルに文字列含まれている前提で、文字列の有る行(レコード)を引っ張ることばっかりやってたのでそっちの発想はまるでなかった次第。

                grepとかオプションもほとんど知らない機能が多すぎる。
                awkやsedも定型的作業ででしか使ってないし、そんなに複雑なことしてないし。
                イロイロわかると面白そうなのは重々承知・・・

                だけどいつまでも頭が追いつかないまま年老いていきそう。
                #スマホしか使わない世代からしたら「グレップなにそれ、オイシイの?」って言われそうな予感。

                親コメント
              • by shibuya (17159) on 2018年03月22日 17時53分 (#3380464) 日記

                >オプションもほとんど知らない機能が多すぎる。

                実機がスマホやスピーカーしか手元にない若い世代の人も

                man grep

                とウェブ検索すればコマンド使用前に確認できる世の中。
                だからそれはそれで全然構わないと思う。
                かけてよいコスト次第ですが。

                親コメント
            • by manmos (29892) on 2018年03月22日 17時21分 (#3380431) 日記

              そういえば、まんまfor f in $(find . なんたら -print) ; do mv $f $f.back ; doneって何度もやったことある。

              #bash派です。

              親コメント
              • by nemui4 (20313) on 2018年03月23日 10時34分 (#3380913) 日記

                >そういえば、まんまfor f in $(find . なんたら -print) ; do mv $f $f.back ; doneって何度もやったことある

                ちょうどさっき特定のlogファイルだけをアーカイブしようとして↑これを思い出したので

                % for f in $(find . -type f -name "ほげ.180*" | grep -v ふが); do gzip $f; done

                とやったらあっさり終わり。
                これだと余計なtempファイルを残すこともないのですっきりしますね。

                #普段決まった仕事ばかりやってるのであんまり頭使ってないのもあって知らなかった・・・

                exp増えた、サンキューサー。

                親コメント
              • ログインシェルはtcsh派なんですが、tcshのforeachは中身がヒストリに残らないので、たまに
                % sh -c 'for f in $(find . なんたら -print) ; do mv $f $f.back ; done'
                とかやったりします。

                #そこまでするぐらなら、とっととbashに乗り換えろよ、と自分でも思うのですが、20年以上使い込んだ.tcshrcが捨てられない…

                親コメント
              • by manmos (29892) on 2018年03月23日 13時26分 (#3381033) 日記

                > ログインシェルはtcsh派なんですが、tcshのforeachは中身がヒストリに残らないので

                ですね。私もほぼ同じ理由でbashにうつりました。
                だいたい、historyとreadlineのためにcshからtcshにしたんだから、historyに残らないとかtsch意味ないやんって。

                親コメント
            • by nemui4 (20313) on 2018年03月22日 14時31分 (#3380297) 日記

              foreach f ( `...` ) でいけるんですね、それいいな。
              (たぶんよく知られてそうだけど知らなかった)

              find . なんちゃら > list1
              で一旦吐き出してからやってた。
              便利だけどあとで消し忘れてごみになりやすい。

              親コメント
            • by Ryo.F (3896) on 2018年03月24日 2時25分 (#3381526) 日記

              % find . なんやかんか -print | xargs grep 条件1 | less

              この場合に「-print」を付ける意味ある?

              親コメント
      • by Ryo.F (3896) on 2018年03月24日 1時51分 (#3381513) 日記

        言うほどよくある話ではない気がするけど。
        FTS_MAX_READDIR_ENTRIES(既定では100,000)を超える数のファイルを対象にしたときに発生して、しかも発生するファイル数は一定ではない、ってわけでしょ?
        ファイル数が多くても、複数ディレクトリにファイルが分散してる場合だとこの現象は発生しなさそうだし。

        参考までに聞いときたいんだけど、どんな場合に発生したことがあるんですか?

        親コメント
        • by manmos (29892) on 2018年03月26日 10時05分 (#3382362) 日記

          つか、減る話はなんぼでもあるわけで、-depthオプションとかあることを考えるとfindがatomicでないことなんて自明でしょう。
          まあ「よく」はないかもしれないけど、それは予想しておけって事ですね。

          #大阪人は「まあ、ようある話」って「よう言います」から。ようしらんけど。

          親コメント
          • by Ryo.F (3896) on 2018年03月26日 20時36分 (#3382743) 日記

            減る話はなんぼでもあるわけで

            意味不明です。

            -depthオプションとかあることを考えるとfindがatomicでないことなんて自明でしょう。

            複数ディレクトリ間でアトミックでないのは自明だけど、
            ディレクトリ内でアトミックでないことは、必ずしも自明じゃないでしょう。
            なので、

            findを実行した時点でのファイルだけをmvしたかったのに、mvされたあとのファイルもfindに引っかかってしまった。
            って、よくあるお話。

            は、ディレクトリ間でそういうことがあった、という違う話を、ディレクトリ内の話と混同したように見えます。

            ディレクトリ内も非アトミックに実装されている可能性がある、
            という意味で予測できる、と言うなら、確かにその通りですが、
            経験したわけでも、コードレビューしたわけでもなければ、後知恵ですね。

            仮に、その可能性を事前に考えていたとしても、
            今回の検証で得られた知見は超えられてないですね。
            FTS_MAX_READDIR_ENTRIESを一つでも超えれば発生する、というわけではないのだから。

            親コメント
typodupeerror

普通のやつらの下を行け -- バッドノウハウ専門家

読み込み中...