Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top
  1. In the "A" directory: find . -type f > a.txt
  2. In the "B" directory: cat a.txt | while read FILENAMES; do touch "$FILENAMES"; done

Result: Step 2 "creates the files" (I mean only with the same filename, but with 0 Byte size) but if there are subdirs in the "A" directory, then step 2 can't create the files in the subdir, because there are no directories in it.

Question: Is there a way, that "touch" can create directories?

share|improve this question
Cross-posted on SuperUser:… – Bobby Jan 17 '11 at 16:04

quick shot:

while read FILENAME
  mkdir -p $(dirname "$FILENAME") && touch "$FILENAME"
done < a.txt

Be aware of special chars (whitespaces, ...) in file-/pathnames and so on ...

share|improve this answer
then you also want double-quotes around the $(...) substitution, to protect against whitespace-splitting of the result, and should figure out how to deal with newlines embedded in the filenames. find's -print0 and using a shell which supports having read use a NUL delimiter may help. – Phil P Jan 17 '11 at 9:59
Phil P is right, you can put quotes around the $(..), even if it contains quotes itself (as in this case) and Bash will do The Right Thing. – Javier Jan 17 '11 at 12:41

I'm on quite a GNU parallel kick lately. Here's a way to do this in one line using that tool:

find A -type d | parallel 'mkdir -p B/$(dirname {})' && find . -type f | parallel 'touch B/{}'

Note that this is inefficient because it runs a lot of extra unneeded mkdir -p for intermediary directories. That should be optimized if you are dealing with really huge directory structures.

share|improve this answer
up vote 2 down vote accepted

in the original, "A" directory:

find . -type f > a.txt

"B" directory:

while read file; do if [[ "$file" = */* ]]; then mkdir -p "${file%/*}"; fi; touch "$file"; done < a.txt
share|improve this answer

This works even if A contains the file:

A/My brother's 12" records dir/My brother's 12" records

(cd A; find . -type f) | (cd B; parallel 'mkdir -p {//}; touch {}')

Having dealt with users creating "creative" filenames I always test script like these on

My brother's 12" records

If it works for that, then chances are good it will not fail.

Thanks to Phil H for giving the basic building blocks.

share|improve this answer

Before doing:

cat a.txt | while read FILENAMES; do touch "$FILENAMES"; done


cat a.txt | sed -e `s|/[^/]*$||` | uniq | while read DIRNAMES; do mkdir -p "$DIRNAMES"; done

As already pointed out, be careful about special char in dirnames/filenames, especially slashes (I would hate to have a file named "aaa/ccc", but it is always possible).

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.