I have a directory (dir1, say) where each sub-directory contains the same contents. Like this:
dir1
sub1
subsub1
file1
file2
subsub2
[etc.]
sub2
[same as in sub1]
sub3
[...]
aberration
So, you see, there’s also one sub-directory which is different.
Then, I have another directory (dir2), which has contents that I would like to use to replace the contents of each of sub1, sub2, sub3, etc., but NOT of aberration. I would like to overwrite any files and directories in the target (where dir2/subsub1 would replace the entire dir1/sub5/subsub1 directory, regardless of its contents). [Edit: I realized I had dir1 and dir2 reversed in this previous sentence. I have edited it to correct the error.]
Is there a single command I can run to accomplish this? I’ve looked at cp with xargs and rsync with a for loop, but I’ve gotten my brain in a twist.
I’m also happy to write this as a shell script, but I’m still lost.
Superficially:
As a technique, it relied on being able to distinguish
aberrationfromsub1etc via the glob patternsub*. Adapt that to suit the details of your environment. If the worst comes to the worst, create a file with the list of non-aberrational directory names:This won’t remove files found under dir2/subN that are not in dir1/subN. For that, you’d probably add:
Be cautious – the
rm -fris dangerous.In a comment, I noted:
To which the response was:
Ah yes, I’m familiar with finding that I was not entirely sane in times long past and that I have to live with the consequences.
The scheme I have in mind, assuming that pathnames do not include spaces, is very simple:
directory-mapping-file
That is, it contains the name of the subdirectory under
dir1and the name underdir2.Directory copying code
The way you use it is then similar to this (being careful to do vaguely appropriate error checking):
Obviously, you can locate the directory mapping file anywhere convenient. Note that unless you are careful (as shown) to use the correct relative names, you can end up with unwanted directory hierarchies under your target directory. Definitely experiment and double-check that the script gives you what you need. Also note that the
cdcommand is done in an explicit sub-shell (the( ... )notation. This isolates the change of directory to the sub-shell, which is generally more resilient that doing thecdin the parent shell. If the error message from thecdcommand is sufficient, then theelseclause is not needed, and you could reduce that all to:Note, too, that I quote the names; that may be old-school shell scripting, but if you ever change to a system where pathnames contain spaces, it is easier to get scripts to work sanely with a variety of shells if you enclose the names in quotes at all times.
A nice refinement is to allow comments and blank lines in the file:
Note that the
\tprobably needs to be an actual tab (but it is more than a little difficult to show a tab in Markdown). I have a script I call nbncl (non-blank, non-comment lines) which encapsulates the logic of thesedcommand shown (though it is actually a non-minimal Perl script). Using that gives: