How do I create an empty file (0 byte size) in all the directories?

Recently I was asked, in a job interview, "how to create a zero size file [I think that means an empty file] in all the folders of the file system?" I found the question a bit strange, I thought of a loop to list all the directory and use touch or maybe go to the root directory and use touch with a recursive option. Do you have any ideas?


That could be ...

find . -type d -exec touch {}/emptyfile \;
  • -type d means "directories"
  • execute the command touch and create a file named "emptyfile"
  • the {} substitutes what is found as a result from find. The / is to make it a valid path+filenane and the escaped ; is to close the command (otherwise it becomes "emptyfile;")

result ...

rinzwind@schijfwereld:~/t$ mkdir 1 2 3 4 5 6 7 8 9 10
rinzwind@schijfwereld:~/t$ ls -ltr */*
ls: cannot access '*/*': No such file or directory
rinzwind@schijfwereld:~/t$ find . -type d -exec touch {}/emptyfile \;
rinzwind@schijfwereld:~/t$ ls -ltr */*
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 5/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 9/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 1/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 8/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 3/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 2/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 10/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 7/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 6/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 4/emptyfile

Mine works but the answer from Peter Cordes is better :)


To do this efficiently, you want to avoid spawning a new touch process for every file you want to create.

This is part of what xargs is good for, batching args into chunks as large as possible, while small enough to fit on the command line of a single process. (Modern Linux has pretty huge limits so it's rarely a problem anymore, xargs rarely has to actually run your command multiple times to handle all the args, but it also lets you avoid having filename subjected to shell word-splitting like in foo $(bar).)

We can use find's own -printf to format additional stuff onto each directory path, specifically the filename we want. The xargs -0 uses a '\0' byte as a separator so this is safe with arbitrary filenames, even including newline. If you weren't using a custom printf format, you could just use -print0 to print 0-separated paths.

  find . -xdev -type d -printf '%p/empty\0'  | xargs -0 echo touch

(in a test directory, that prints touch ./empty ./2/empty ./1/empty, not touch ./empty, touch ./1/empty, etc. so it's running one touch for multiple files.)

mktemp only accepts a single template, but if we want some randomness in the naming to reduce the chance of just touching an existing file by accident, you could do this.

  find . -xdev -type d -printf "%p/empty.$RANDOM\0"  | xargs -0 echo touch

Note that it's the same 15-bit random number in every directory, because "$RANDOM" is expanded once by bash before find starts. You could use $(date +%s).$RANDOM or whatever you want as part of the filename.


With an SSD or tmpfs, CPU might be the bottleneck here. Or if you're lucky and metadata I/O on a magnetic disk happens to be mostly contiguous because you're touching every directory (and allocating a bunch of new inodes), even a rotational disk could maybe keep up somewhat decently. Although you're probably not touching directories in the order they're laid out on disk.

And regardless, there's no need to waste lots of CPU time starting processes for something that should be I/O limited.


Ways that don't work:

  • find -exec touch {} + batches args, but -exec touch {}/empty + refuses to work when {} isn't by itself.

  • xargs -I {} echo touch {}/emptyfile implies -L 1 (only process one "line" of input for each invocation of the command, whether that's an actual line or a 0-separated string with xargs -0). So we can't use xargs to modify each arg if we want to take advantage of it for batching args.


find /mountpoint -xdev -type d -exec mktemp -p {} \;

A quite obvious aspect is you may or may not need root access to actually create files under /mountpoint.

There are two non-obvious aspects:

  1. You said "in all the folders of the file system", so we start from specific /mountpoint and do not enter other filesystems (-xdev).

    If there are other filesystems mounted deeper in the tree, e.g. in /mountpoint/foo/another/mntpoint, then -xdev will prevent us from entering them. Still these filesystems may mask entire subtrees that belong to the filesystem in question. In the best case a filesystem mounted in /mountpoint/foo/another/mntpoint masks an empty mntpoint directory of the filesystem in question. So we cannot easily reach "all the folders of the file system".

    With root access we can mount --bind /mountpoint /somewhere/else beforehand. With --bind (as opposed to --rbind, see man 8 mount) mntpoint deep in /somewhere/else will not replicate the submount from /mountpoint/foo/another/mntpoint. This way we can access mntpoint that belongs to the filesystem in question.

    This is still not enough. If the filesystem in question is Btrfs then possibly /mountpoint gives access to some subvolume but not to the entire filesystem (compare this question).

    In general a subtree of any(?) mounted filesystem can be bind-mounted to another directory. After you unmount the original mountpoint, the other directory gives access to a fragment of the filesystem. Our /mountpoint may be "the other directory" in the first place and therefore it may not give access to the entire filesystem. You don't know this in advance.

    The conclusion is: if the phrase is strictly "all the folders of the file system" (as opposed to "all subdirectories" which is quite straightforward) then you need to make sure you don't miss any part of the filesystem. Only then use the find … command given at the beginning of this answer.

  2. Solutions with touch emptyfile or so do not necessarily "create a zero size file". What if the interviewer has already created a non-empty emptyfile in one of the directories? A trap! If non-empty emptyfile exists then touch will neither create it, nor the file will be empty. Effectively you will strictly fail to "create a zero size file" in the directory with the trap. This is the reason I used mktemp. The tool will try hard to really create a new empty regular file.


This will create a unique name empty file in each directory starting with and descending from the current directory including hidden directories if you want to.

First, get the directories list with tree.

Then, pass them to xargs like so:

tree --noreport -dfi | xargs -L 1 -I {} echo touch {}/emptyfile_"$(date +%s)"

Or, to a while loop like so:

tree --noreport -dfi | \
while read -r d; do echo touch "$d"/emptyfile_"$(date +%s)"; done

Or, even to a for loop (if the directory names contain no spaces) like so:

for d in $(tree --noreport -dfi); do echo touch "$d"/emptyfile_"$(date +%s)"; done
  • echo is there to prevent unintentional creation of files while testing. When satisfied with the output, remove echo to create files.

  • --noreport omits printing of the file and directory report at the end of the tree listing.

  • -dfi lists directories only, prints the full path prefix for each directory and makes tree not print the indentation lines.

  • Use -dfia instead of -dfi to include hidden directories as well.

  • "$(date +%s)" appends current timestamp to filename like this emptyfile_1618679443 making it unique from existing files in each directory. Notice you can change this to a random number like 67639871206723 if you need a fixed file name.

  • xargs -L 1 -I {} reads the input one line at a time and assigns it to {}.