3

I have a folder structure like this

|_folder1
| |_folder1.1
| | |_folder1.1.1
| |   |_img00
| |   |_...
| |_folder1.2
|   |_img00
|   |_...
|_folder2
  |_img00
  |_...

I want the script that combines images into pdfs to run at the leaf directories

2 Answers2

4

Now that you have the list of subdirectories, to get the leaf directories only, check for each directory to see if it has no subdirectory: check if *(/DN) is empty. You can add the glob qualifier Y1 to stop listing matches after the first.

for d in **/*(/DN); do
  sub=($d/*(/DNY1))
  if (($#sub)); then continue; fi
  process_leaf_directory $d
done

With most filesystems, there's an easier way: a leaf directory has a link count of 2 (only the entry for it in its parent directory and its . entry, whereas a non-leaf directory also has the .. entries in its subdirectories). This makes the filtering simpler: check for a link count of 2 with the glob qualifier l.

for d in **/*(/DNl2); do
  process_leaf_directory $d
done
3

The following find command would find every leaf directory under the current directory, and execute a script within it:

find . -type d -links 2 -execdir /path/to/script.sh some arguments here \;

This would execute the command given to -execdir in each leaf directory under the current directory.

The same, but using zsh (does not consider hidden names):

for dirpath in ./**/*(/l2); do
    ( cd "$dirpath" && /path/to/script.sh some arguments here )
done

The pattern ./**/*(/l2) would expand to the pathname of any leaf directories under the current directory. The ** matches recursively down into directory structures while *(/l2) would match any name that is a directory with a link count of exactly 2 (i.e. it's a directory with no subdirectories, a fact also used by the find command above).

Note that on some filesystems, like Apple's APFS, directories may have a link count greater than 2 even when they have no subdirectories. On BTRFS, the link count for directories is always 1. This solution would therefore not work on those filesystems.

Related:

Kusalananda
  • 333,661
  • -execdir runs the script in the parent of the selected directory, not the directory itself. – Stéphane Chazelas Oct 04 '19 at 10:11
  • That -links 2 trick only works in some traditional Unix file systems and if no directory hard links other than . and .. are ever created. It won't work on btrfs for instance where the link count for directories is always 1. – Stéphane Chazelas Oct 04 '19 at 10:12