【问题标题】:for-loop for every folder in a directory, excluding some of them目录中每个文件夹的for循环,不包括其中一些
【发布时间】:2012-10-16 15:50:46
【问题描述】:

非常感谢您的帮助!

我在 bash 中有这段代码:

for d in this_folder/*    
    do    
        plugin=$(basename $d)
        echo $plugin'?'
        read $plugin
    done

这就像一个魅力。对于“this_folder”中的每个文件夹,将其作为问题回显并将输入存储到具有相同名称的变量中。

但现在我想排除一些文件夹,例如,它会询问该目录中的每个文件夹,前提是它们不是以下任何文件夹:全局、插件和 css。

有什么想法可以实现吗?

谢谢!

更新:

这是最终代码的样子:

base="coordfinder|editor_and_options|global|gyro|movecamera|orientation|sa"

> vt_conf.sh
echo "# ========== Base"     >> vt_conf.sh
for d in $orig_include/@($base)
do
    plugin=$(basename $d)
    echo "$plugin=y"         >> vt_conf.sh
done
echo ''                      >> vt_conf.sh
echo "# ========== Optional" >> vt_conf.sh
for d in $orig_include/!($base)
do
    plugin=$(basename $d)
    echo "$plugin=n"         >> vt_conf.sh
done

【问题讨论】:

    标签: bash for-loop


    【解决方案1】:

    如果您有最新版本的 bash,则可以使用扩展 glob (shopt -s extglob):

    shopt -s extglob
    
    for d in this_folder/!(global|plugins|css)/   
    do    
        plugin=$(basename "$d")
        echo $plugin'?'
        read $plugin
    done
    

    【讨论】:

    • 这是一个很好的选择,但是如果this_folder中既有目录又有文件也会返回所有文件。如果您只是在for 行的末尾(在! 标准之后)放一个尾随'/',这将很好地工作。另外,我建议(对您和 OP)在引号之间加上对 $d 的引用,这样可以用空格覆盖文件规范。
    • @CharlesRobertoCanato:很好的建议,我已经添加了你的建议
    • 只是为像我这样的愚蠢的人解释一下:在您的脚本中使用感叹号排除语句之前,必须执行命令shopt -s extglob。花了一些时间意识到这一点......
    【解决方案2】:

    您可以使用continue 跳过循环的一次迭代:

    for d in this_folder/*    
        do    
            plugin=$(basename $d)
            [[ $plugin =~ ^(global|plugins|css)$ ]] && continue
            echo $plugin'?'
            read $plugin
        done
    

    【讨论】:

      【解决方案3】:

      如果您只想排除名为 global、css、plugins 的目录。这可能不是一个优雅的解决方案,但会做你想做的。

      for d in this_folder/*    
      do  
          flag=1
          #scan through the path if it contains that string
          for i in "/css/" "/plugins/" "/global/"
          do
      
          if [[ $( echo "$d"|grep "$i" ) && $? -eq 0 ]]
          then
            flag=0;break;
          fi
          done
      
          #Only if the directory path does NOT contain those strings proceed
          if [[ $flag -eq 0 ]]
          then
          plugin=$(basename $d)
          echo $plugin'?'
          read $plugin
          fi
      
      
      done
      

      【讨论】:

      • 您可以使用 continue 2 而不是 flag=0;break;。然后删除后面的if [[ $flag -eq 0 ]] ... wrapper。
      • @dubiousjim:是的,你是对的,但我只是想让 OP 的脚本更易于理解。
      【解决方案4】:

      您可以使用findawk 来构建目录列表,然后将结果存储在变量中。类似这样的东西(未经测试):

      dirs=$(find this_folder -maxdepth 1 -type d -printf "%f\n" | awk '!match($0,/^(global|plugins|css)$/)')
      for d in $dirs; do
          # ...
      done
      

      2019 年 5 月 16 日更新:

      while read -r d; do
          # ...
      done < <(gfind  -maxdepth 1 -type d -printf "%f\n" | awk '!match($0,/^(global|plugins|css)$/)')
      

      【讨论】:

      • 如果文件名包含与现有文件匹配的空格或外壳通配符,则会中断。
      • @tripleee 啊,好吧,我确实说它未经测试...?无论如何,我添加了一个解决方案while read -r
      【解决方案5】:

      虽然How to exclude some files from the loop in shell script 被标记为此 Q/A 的骗子并已关闭,但 Q 专门询问了在 BASH 脚本中排除 文件 的问题,这正是我需要(在脚本中检查本地 URL 中链接片段(# 之后的部分)的有效性。这是我的解决方案。

          for FILE in *
          do
              ## https://linuxize.com/post/how-to-check-if-string-contains-substring-in-bash/
              if [[ "$FILE" == *"cnp_"* ]]
              then
                  echo 'cnp_* file found; skipping'
                  continue
              fi
              ## rest of script
          done
      

      输出:

          cnp_* file found; skipping
      
          ----------------------------------------
          FILE: 1 | NAME: linkchecker-test_file1.html
          PATH: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html
      
           RAW LINE: #bookmark1
          FULL PATH: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html#bookmark1
               LINK: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html
           FRAGMENT: bookmark1
             STATUS: OK
          ...
      

      我的测试目录包含 3 个文件,其中一个我想排除(旧网站的网页抓取:包含大量已弃用链接片段的索引)。

      [victoria@victoria link_fragment_tester]$ tree
      .
      ├── cnp_members-index.html
      ├── linkchecker-test_file1.html -> /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html
      └── linkchecker-test_file2.html -> /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file2.html
      
      0 directories, 3 files
      [victoria@victoria link_fragment_tester]$ 
      

      【讨论】:

        【解决方案6】:

        拆分路径,检查每个要忽略的文件夹名称。
        如果你想增加以后要忽略的文件夹的数量,这样忽略文件夹很方便。 (它们在这里存储在被忽略的文件夹中)。
        在代码中添加了 cmets。
        这在 Ubuntu 20.04.2 中对我来说很好

        #!/bin/bash
        shopt -s globstar #necessary for search ./**/*
        ignoredfolders=("folder1name" "folder2name")
        
        for i in ./**/*
        do
            #pattern for splitting forward slashes into empty spaces
            ARRAY=(${i//\//" "} ); 
            for k in "${ignoredfolders[@]}"; do
                #does path (splitted in ARRAY) contain a foldername ($k) to be ignored? 
                if [[ " ${ARRAY[@]} " =~  "$k"  ]]; then
                    #this skips this loop and the outer loop
                    continue 2
                fi
            done
            # all ignored folders are ignored, you code sits here...
            #code ...
            #code ...
        
        done
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-11-02
          • 1970-01-01
          • 2017-09-20
          • 1970-01-01
          • 2016-03-11
          • 1970-01-01
          相关资源
          最近更新 更多