【问题标题】:Looping through each file in directory - bash遍历目录中的每个文件 - bash
【发布时间】:2021-01-16 13:31:27
【问题描述】:

我正在尝试对目录中的每个文件执行某些操作,但是它正在执行的顺序存在问题。它应该一次做一个文件。长线(解压缩,grepping,压缩)在没有脚本的单个文件上工作正常,因此循环存在问题。有什么想法吗?

脚本应该遍历每个压缩文件并查找 word1 或 word2。如果其中至少存在一个,则:

  1. 解压文件
  2. grep word1 和 word2 并保存到 file_done
  3. 删除解压文件
  4. 使用原始名称将 file_done 压缩到 /donefiles/
  5. 从原始目录中删除 file_done
    #!/bin/bash
    for file in *.gz; do
    counter=$(zgrep -c 'word1\|word2' $file)
    if [[  $counter -gt 0 ]]; then
    echo $counter
    for file in *.gz; do
    filenoext=${file::-3}
    filedone=${filenoext}_done
    echo $file
    echo $filenoext
    echo $filedone
    gunzip  $file | grep 'word1\|word2'  $filenoext > $filedone | rm -f $filenoext |  gzip -f  -c  $filedone > /donefiles/$file | rm -f $filedone
    done
    else
    echo "nothing to do here"
    fi
    done

【问题讨论】:

    标签: bash loops for-loop grep


    【解决方案1】:

    您提供的代码片段存在一些问题,例如循环和错误管道不需要嵌套 (整行gunzip $file | grep 'word1\|word2' $filenoext > $filedone | rm -f $filenoext | gzip...)。

    还请注意,只有当 *.gz 文件的名称中没有空格(或特殊字符)时,您的代码才能正常工作。 zgrep -c 'word1\|word2' 也将匹配 line_starts_withword1_orword2_ 之类的字符串。

    这是脚本的工作版本:

    #!/bin/bash
    for file in *.gz; do
            counter=$(zgrep -c -E 'word1|word2' $file) # now counter is the number of word1/word2 occurences in $file
            if [[ $counter -gt 0 ]]; then
                    name=$(basename $file .gz)
                    zcat $file | grep -E 'word1|word2' > ${name}_done
                    gzip -f -c ${name}_done > /donefiles/$file
                    rm -f ${name}_done
            else
                    echo 'nothing to do here'
            fi
    done
    

    我们可以在这里改进的是:

    • 由于我们无论如何都要解压文件以检查 word1|word2 是否存在,我们可以对临时文件执行此操作并避免双重解压缩
    • 我们不需要计算文件中有多少个 word1 或 word2,我们可以只检查它们是否存在
    • ${name}_done 可以是自动清理的临时文件
    • 我们可以使用 while 循环来处理带空格的文件名
    #!/bin/bash
    tmp=`mktemp /tmp/gzip_demo.XXXXXX` # create temp file for us
    trap "rm -f \"$tmp\"" EXIT INT TERM QUIT HUP # clean $tmp upon exit or termination
    find . -maxdepth 1 -mindepth 1 -type f -name '*.gz' | while read f; do
            # quotes around $f are now required in case of spaces in it
            s=$(basename "$f") # short name w/o dir
            gunzip -f -c "$f" | grep -P '\b(word1|word2)\b' > "$tmp"
            [ -s "$tmp" ] && gzip -f -c "$tmp" > "/donefiles/$s" # create archive if anything is found
    done
    
    

    【讨论】:

    • 不要忘记在变量扩展或带有空格制表符或换行符的文件名周围添加双引号 counter=$(zgrep -c -E 'word1|word2' $file)counter=$(zgrep -c -E 'word1|word2' "$file") 并且由于 grep 的返回状态显示是否找到模式,然后就做if zgrep -qcE 'word1|word2' "$file"; then name=${file%.gz} ...
    【解决方案2】:

    看起来你在外循环里面有一个内循环:

    #!/bin/bash
    for file in *.gz; do
        counter=$(zgrep -c 'word1\|word2' $file)
        if [[  $counter -gt 0 ]]; then
            echo $counter
            for file in *.gz; do #<<< HERE
                filenoext=${file::-3}
                filedone=${filenoext}_done
                echo $file
                echo $filenoext
                echo $filedone
                gunzip  $file | grep 'word1\|word2'  $filenoext > $filedone | rm -f $filenoext |  gzip -f  -c  $filedone > /donefiles/$file | rm -f $filedone
            done
        else
            echo "nothing to do here"
        fi
    done
    

    如果其中一个文件包含file1或file2,则内部循环会遍历目录中的所有文件。你可能想要这个:

    #!/bin/bash
    for file in *.gz; do
        counter=$(zgrep -c 'word1\|word2' $file)
        if [[  $counter -gt 0 ]]; then
            echo $counter
            filenoext=${file::-3}
            filedone=${filenoext}_done
            echo $file
            echo $filenoext
            echo $filedone
            gunzip  $file | grep 'word1\|word2'  $filenoext > $filedone | rm -f $filenoext |  gzip -f  -c  $filedone > /donefiles/$file | rm -f $filedone
        else
            echo "nothing to do here"
        fi
    done
    

    【讨论】:

      猜你喜欢
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 2011-01-31
      • 2012-07-25
      • 2014-10-02
      • 1970-01-01
      • 2019-01-16
      • 2011-08-05
      相关资源
      最近更新 更多