【问题标题】:Linux: Removing files that don't contain all the words specifiedLinux:删除不包含所有指定单词的文件
【发布时间】:2010-10-11 12:12:23
【问题描述】:

在目录中,如何删除缺少任何指定单词的文件,以便只留下包含所有单词的文件?我尝试使用 grep 和 rm 命令编写一个简单的 bash shell 脚本,但我迷路了。我是 Linux 的新手,任何帮助将不胜感激

【问题讨论】:

    标签: linux bash file shell


    【解决方案1】:

    首先,删除文件列表:

    rm flist
    

    然后,对于每个单词,如果文件包含该单词,则将文件添加到文件列表中:

    grep -l WORD * >>flist
    

    然后排序,唯一化并得到一个计数:

    sort flist | uniq -c >flist_with_count
    

    所有那些在 flsit_with_count 中没有字数的文件都应该被删除。格式为:

    2 file1
    7 file2
    8 file3
    8 file4
    

    如果有 8 个单词,那么 file1 和 file2 应该被删除。我将把脚本的编写/测试留给你。

    好的,你说服了我,这是我的剧本:

    #!/bin/bash
    rm -rf flist
    for word in fopen fclose main ; do
        grep -l ${word} *.c >>flist
    done
    rm $(sort flist | uniq -c | awk '$1 != 3 {print $2} {}')
    

    这会删除目录中没有三个单词的文件:

    【讨论】:

      【解决方案2】:

      怎么样:

      grep -L foo *.txt | xargs rm
      grep -L bar *.txt | xargs rm
      

      如果文件包含foo,则第一行将删除它。

      如果文件包含bar,则第二行将删除它。

      只应保留包含foobar 的文件

      -L, --files-without-match
           Suppress normal output; instead print the  name  of  each  input
           file from which no output would normally have been printed.  The
           scanning will stop on the first match.
      

      另请参阅@Mykola Golubyev's post 以了解如何放置在循环中。

      【讨论】:

      • 我认为带有 foo OR bar 的文件将被删除。
      • 我认为 -v 是否定 grep 的正确方法,因为它不会在第一场比赛中停止?
      • 否,-v 将返回所有不包含该单词的 LINES。
      【解决方案3】:

      这将删除所有不包含单词 PingSent

      的文件
      grep -L 'Ping\|Sent' * | xargs rm
      

      【讨论】:

      • 这不会删除仅包含其中一个单词的文件。
      • 是的,我已经注意到了,然后点击删除,但为时已晚。
      【解决方案4】:
      list=`Word1 Word2 Word3 Word4 Word5`
      for word in $list
          grep -L $word *.txt | xargs rm
      done
      

      【讨论】:

        【解决方案5】:

        以上答案的补充:使用换行符作为分隔符来处理带空格的文件名!

        grep -L $word $file | xargs -d '\n' rm
        

        【讨论】:

          【解决方案6】:

          grep -L 单词 | xargs rm

          【讨论】:

            【解决方案7】:

            要执行相同的匹配文件名(不是上述大多数解决方案的文件内容),您可以使用以下内容:

            for file in `ls --color=never | grep -ve "\(foo\|bar\)"`
            do
               rm $file
            done
            

            根据 cmets:

            for file in `ls`
            

            不应使用。下面在不使用ls的情况下做同样的事情

            for file in *
            do
              if [ x`echo $file | grep -ve "\(test1\|test3\)"` == x ]; then
                rm $file
              fi
            done
            

            -ve 会反转对文件名中 foo 或 bar 的正则表达式模式的搜索。 要添加到列表中的任何其他单词都需要用 \| 分隔。 例如一\|二\|三

            【讨论】:

            • 对于 'ls' 中的文件是个坏主意。
            • 好点。相应地进行了编辑,但我不喜欢这使它变得复杂。你能想出更有效的方法吗?
            【解决方案8】:

            您可以尝试这样的方法,但它可能会损坏 如果模式包含 shellgrep 元字符:

            (在这个例子中一二三是模式)

            for f in *; do
              unset cmd
              for p in one two three; do
                cmd="fgrep \"$p\" \"$f\" && $cmd"
              done
              eval "$cmd" >/dev/null || rm "$f"  
            done 
            

            【讨论】:

              猜你喜欢
              • 2016-03-09
              • 2017-02-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-10-15
              • 2020-05-11
              • 1970-01-01
              • 2016-04-24
              相关资源
              最近更新 更多