【问题标题】:unix bash find file directories with 2 explicit file extensionsunix bash 查找具有 2 个显式文件扩展名的文件目录
【发布时间】:2014-11-28 00:47:31
【问题描述】:

我正在尝试创建一个小型 bash 脚本,该脚本实质上是查看包含数百个子目录的目录。在其中一些子目录中包括一个 textfile.txt 和一个 htmlfile.html,其中名称 textfile 和 htmlfile 是可变的。

我只关心同时具有.txt和.html的子目录,其他所有子目录都可以忽略。

然后我想列出同一子目录中的所有 .html 文件和 .txt 文件

这似乎是一个很容易解决的问题,但我不知所措。我能真正开始工作的是一行代码,它输出具有 .html 文件或 .txt 的子目录,与它们所在的实际子目录没有关联,而且我在 bash 脚本方面很新,所以我不能继续前进

#!/bin/bash

files="$(find ~/file/ -type f -name '*.txt' -or -name '*.html')"

for file in $files
do 
echo $file

done

【问题讨论】:

  • 发布你目前所拥有的。
  • 以上更新,谢谢
  • 我觉得应该有一种方法可以通过 find 本身来做到这一点,但我正在努力思考目前可能是什么。这意味着我得到的最佳答案(我目前没有时间写出来)将涉及使用-type f \( -name -o -name \) -printf '%h\n',然后将其传递给 awk/sort+uniq -c 以查找超过一个输出条目。
  • @EtanReisner 完全正确!并使用 uniq -d 仅获取重复的条目,例如只有两个文件都在哪里。将结果传送到xargs find ... 以列出所有文件...
  • @jm666 您可以有一个包含多个 *.html 文件但没有 *.txt 文件的目录,反之亦然。如果你只打印目录名,你会在这两种情况下得到重复的行,你最终会得到错误的匹配。

标签: linux bash unix


【解决方案1】:

以下find 命令会检查每个子目录,如果它有两个 htmltxt 文件,它会列出所有文件:

find . -type d -exec env d={} bash -c 'ls "$d"/*.html &>/dev/null && ls "$d"/*.txt &>/dev/null && ls "$d/"*.{html,txt}' \;

解释:

  • find . -type d

    这会查找当前目录的所有子目录。

  • -exec env d={} bash -c '...' \;

    这会将环境变量d 设置为找到的子目录的值,然后执行包含在单引号中的bash 命令(见下文)。

  • ls "$d"/*.html &>/dev/null && ls "$d"/*.txt &>/dev/null && ls "$d/"*.{html,txt}

    这是执行的 bash 命令。它由三个语句和-ed 一起组成。第一个检查目录d 是否有任何html 文件。如果是这样,第二个语句运行并检查是否有任何 txt 文件。如果是,则执行最后一条语句,并列出目录d 中的所有html 和txt 文件。

此命令对于所有包含空格、制表符或其他难读字符的文件和目录名称都是安全的。

【讨论】:

    【解决方案2】:

    您可以通过使用 globstar 选项递归搜索来做到这一点:

    shopt -s globstar
    for file in **; do
        if [[ -d $file ]]; then
            for sub_file in "$file"/*; do
                case "$sub_file" in
                    *.html)
                        html=1;;
                    *.txt)
                        txt=1;;
                esac
            done
            [[ $html && $txt ]] && echo "$file"
            html=""
            txt=""
        fi
    done
    

    【讨论】:

      【解决方案3】:

      你可以使用 -o

      #!/bin/bash
      
      files=$(find ~/file/ -type f -name '*.txt' -o -name '*.html')
      
      for file in $files
      do 
      echo $file
      
      done
      

      【讨论】:

      • -or -o 只是不是POSIX。
      【解决方案4】:
      #!/bin/bash
      
      #A quick peek into a dir to see if there's at least one file that matches pattern
      dir_has_file() { dir="$1"; pattern="$2";
        [ -n "$(find "$dir" -maxdepth 1 -type f -name "$pattern" -print -quit)" ]
      }
      
      #Assumes there are no newline characters in the filenames, but will behave correctly with subdirectories that match *.html or *.txt
      find "$1" -type d|\
        while read d
        do
          dir_has_file "$d" '*.txt' && 
          dir_has_file "$d" '*.html' &&
          #Now print all the matching files
          find "$d" -maxdepth 1 -type f -name '*.txt' -o -name '*.html'
       done
      

      此脚本将要查看的根目录作为第一个参数 ($1)。

      【讨论】:

        【解决方案5】:

        test 命令是您需要检查每个子目录中每个文件是否存在的命令:

        find . -type d -exec sh -c "if test -f {}/$file1 -a -f {}/$file2 ; then ls {}/*.{txt,html} ; fi" \;
        

        其中$file1$file2 是您要查找的两个.txt 和.html 文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-12
          • 2012-01-26
          • 1970-01-01
          • 2012-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-29
          相关资源
          最近更新 更多