3

For the following tree structure:

    .
└── dir1
    └── dir2
        └── dir3

What would be a simple way to create a file (could be empty), for every directory, so the resulting tree will look like:

.
├── dir1
│   ├── dir2
│   │   ├── dir3
│   │   │   └── README
│   │   └── README
│   └── README
└── README

2 Answers2

3

With zsh:

touch -- README **/*(N/e[REPLY+=/README])

It combines recursive globbing (**/*) with glob qualifiers, which here are:

  • Nullglob: doesn't trigger an error if there's no match.
  • /: restrict to files of type directory
  • e[code]: evaluates the code for each file, here appending /README to file path (stored in $REPLY in the evaluated code).

Or you could use an anonymous function which is passed the list of directories, and which appends the /README to each in the arguments it passes to touch:

() {touch -- $^@/README} . **/*(N/)

(with rc-style array expansion for the anonymous function @rguments using the $^array syntax).

In all those, you can add the Dotglob glob qualifier to also add README to hidden directories.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
2

You can do that with find:

find . -mindepth 1 -type d -exec touch "{}/README" \;

Explanation

  • -mindepth 1 will set the minimum depth, to avoid including the current directory
  • -type d will only find directories
  • -exec will run a command
  • {} contains the path of the found directory

If you want to use only builtin shell commands:

for dir in *; do if [ -d "$dir" ]; then touch "$dir/README"; fi; done

Explanation

  • for will loop over every element in *, meaning all files in the current directory. dir will contain the current element during the loop.
  • if [ -d $dir ] checks if the element is a directory and only then
  • creates a file called README in the directory name contained in $dir
mashuptwice
  • 1,283
  • 5
  • 22
  • Note that arguments that include (contain) `{}` as a substring are not guaranteed to work. – G-Man Says 'Reinstate Monica' Mar 25 '22 at 06:36
  • @G-ManSays'ReinstateMonica' could you name one example where that would fail? – mashuptwice Mar 25 '22 at 12:32
  • I can’t give *specific* examples where it would fail, but see (1) [Wildcard’s answer](https://unix.stackexchange.com/q/321697/80216#321753) — scroll down to “**`find` in combination with `sh`**” and read the second bullet. Or see (2) [jlliagre’s comment](https://unix.stackexchange.com/questions/202391/understanding-find1s-exec-option-curly-braces-plus-sign/202409#comment505495_202409) on [my answer](https://unix.stackexchange.com/q/202391/80216#202409). … (Cont’d) – G-Man Says 'Reinstate Monica' Mar 25 '22 at 20:43
  • (Cont’d) … In an attempt to get specific, I’d say that you’re depending on behavior that may be unique to GNU ``find``, so you’d be in danger on any busybox-based system (e.g., ESXi), or on non-Linux systems like \*BSD, HP-UX, Solaris, etc. – G-Man Says 'Reinstate Monica' Mar 25 '22 at 20:43