3
  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?

1

5 Answers 5

8

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

2
  • 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, 2011 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, 2011 at 12:41
2

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.

2

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
1

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.

0

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .