Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using shell to finds directories that do not have a specified pattern of files in the folder

The directory tree is like this:

.
├── A_123
│   └── 123.txt
├── A_456
│   ├── tmp
│   └── tmp.log
└── A_789
    └── 789.txt

There're 3 directories (A_123, A_456, A_789). The pattern of a directory name is: A_{numbers} and the file I'm interested in is {numbers}.txt.

I was wondering whether there's a way to get the directories A_{numbers} that has no {numbers}.txt file in them. For example above, this script should return:

./A_456

as A_456 doesn't have 456.txt in its folder but A_123 and A_789 have their {numbers}.txt files in the relevant folder.

Anyone has ideas about this? Thanks!

like image 528
Hanfei Sun Avatar asked Dec 04 '25 12:12

Hanfei Sun


2 Answers

Here's one approach:

for dir in *;do 
  if [ $(find "$dir" -maxdepth 1 -regex '.*/[0-9][0-9]*\.txt' | wc -l) = 0 ]; then 
    echo $dir
  fi
done
like image 106
Vaughn Cato Avatar answered Dec 06 '25 03:12

Vaughn Cato


Since the A_[0-9] directories are not nested, you can easily do this with a glob in a loop. This implementation is pure bash, and does not spawn in external utilities:

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

There are some problems with this implementation. It will match a file such as "12ab.txt" and requires loading all the filenames for a directory into the array.

Here is another method in bash that does a more accurate filename matching:

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
like image 22
jordanm Avatar answered Dec 06 '25 04:12

jordanm