bash 用于识别包含“a.txt”和“b.txt”的子文件夹的脚本

bash script to identify sub-folder containing both `a.txt` and `b.txt`

给定一个包含许多深层嵌套文件夹的工作目录,我想要一个脚本来列出所有子文件夹的裸文件夹路径,这些子文件夹直接包含 a.txt 文件和一个 b.txt 文件。

文件名是完全固定的,因此无需支持通配符/正则表达式(尽管很高兴知道该解决方案是否确实支持它。)


作为参考,接下来我将对脚本执行的操作是生成每个 a.txtb.txt 对的差异。但我不希望一旦我找到每一对就太难了。


当我说 'bash' 时,技术上我的意思是 Windows 10 上的 msysgit - git bash。但是我'我希望这些细节不重要

带有 findbash 以及一个循环。

#!/usr/bin/env bash

find . -type d ! -name . -exec bash -O nullglob -O extglob -c '
  for d; do
    files=("$d"/@(a|b).txt)
    if (( ${#files[*]} == 2 )); then
      echo diff "${files[0]}" "${files[1]}"
    fi
  done
' _ {} +
  • . 是当前工作目录。
  • nullglob可能不需要,只是我的习惯而已
  • 由于 @(a|b).txt 模式,需要 extglob,尽管它可以用 files=("$d"/[ab].txt) 替换而不需要 extglob
  • 如果您对输出满意,请删除 echo

您只需要包含 a.txtb.txt 的目录路径。

给定

$: find -name '[ab].txt'
./1/3/a.txt
./1/3/b.txt
./1/a.txt
./2/b.txt

尝试

shopt -s globstar # ** matches zero or more subdirs
for d in **/a.txt # match a variable depth for the loop var
do [[ -e "${d%/a.txt}/b.txt" ]] && echo "${d%/a.txt}"
done
1/3

globstar 让两个星号 (**) 代表任意数量(零个或更多)的子目录,因此

$: echo **/a.txt
1/3/a.txt 1/a.txt

这将搜索限制为仅可能正确的路径。

[[ -e "${d%/a.txt}/b.txt" ]]

剥离已知文件并检查另一个文件,正确地 returns 仅 1/3 作为包含两个文件的单独目录。

它应该非常有效,如果有多个命中,它也能正常工作。

$: find -name '[ab].txt'
./1/3/a.txt
./1/3/b.txt
./1/a.txt
./2/4/5/a.txt
./2/4/5/b.txt
./2/b.txt

$: for d in **/a.txt; do [[ -e "${d%/a.txt}/b.txt" ]] && echo "${d%/a.txt}"; done
1/3
2/4/5