目录树是这样的:
.
├── A_123
│ └── 123.txt
├── A_456
│ ├── tmp
│ └── tmp.log
└── A_789
└── 789.txt
有3个目录(A_123,A_456,A_789)。目录名称的模式为:A_{numbers}
,我感兴趣的文件是{numbers}.txt
。
我想知道是否有一种方法可以获取其中没有{numbers}.txt
文件的目录A_{numbers}
。例如,该脚本应返回:
./A_456
由于A_456
在其文件夹中没有456.txt
,但是A_123
和A_789
在相关文件夹中具有{numbers}.txt
文件。
有人对此有想法吗?谢谢!
这是一种方法:
for dir in *;do
if [ $(find "$dir" -maxdepth 1 -regex '.*/[0-9][0-9]*.txt' | wc -l) = 0 ]; then
echo $dir
fi
done
由于a_ [0-9]目录未嵌套,因此您可以在循环中轻松地执行此操作。此实现是纯粹的狂欢,并且不会在外部公用事业中产生:
for d in A_[0-9]*/; do # the trailing / causes only directories to be matched
files=("$d"/[0-9]*.txt) # populate an array with matching text files
((!${#files})) && echo "$d" # echo $d if the array is empty
done
此实现存在一些问题。它将匹配诸如" 12ab.txt"之类的文件,并需要将目录的所有文件名加载到数组中。
这是bash中的另一种方法,可以更准确地匹配:
re='^[0-9]+[.]txt$'
for d in A_[0-9]*/; do
for f in *; do
if [[ -f $f && $f =~ $re ]]; then
echo "$d"
break
fi
done
done
其他几个答案有轻微的变化:使用bash扩展模式匹配:
shopt -s extglob nullglob
for dir in A_+([0-9]); do
files=($dir/+([0-9]).txt)
(( ${#files[@]} == 0 )) && echo $dir
done
for file in *; do
if [[ "$file" =~ ^A_([0-9]+)$ && ! -f "$file/${BASH_REMATCH[1]}.txt" ]]; then
echo $file;
fi
done
如何工作:
- 使用REGEXP(请注意
=~
)检查文件/文件夹的名称为" A_",然后是数字。 - 同时,它捕获数字(请注意括号),并将它们存储在
${BASH_REMATCH[1]}
中 - 接下来,检查文件夹是否包含
{number}.txt
。 - 如果没有,请呼应文件夹的名称。