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?

link|improve this question

79% accept rate
Cross-posted on SuperUser: superuser.com/questions/234185/… – Bobby Jan 17 '11 at 16:04
feedback

5 Answers

quick shot:

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

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

link|improve this answer
2  
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
feedback

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.

link|improve this answer
feedback

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.

link|improve this answer
feedback
up vote 1 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
link|improve this answer
feedback

Before doing:

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

do:

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).

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

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