表面上:
cd /path/to/dir1
cp -rf sub* /path/to/dir2
作为一种技术,它依赖于能够通过 glob 模式 sub* 区分 aberration 和 sub1 等。调整它以适应您的环境的细节。如果最坏的情况出现在最坏的情况下,请创建一个包含非异常目录名称列表的文件:
cp -rf $(<non-aberrational-names) /path/to/dir2
这不会删除在 dir2/subN 下找到但不在 dir1/subN 中的文件。为此,您可能会添加:
cd /path/to/dir2 &&
rm -fr sub*
cd /path/to/dir1
cp -fr sub* /path/to/dir2
小心 - rm -fr 很危险。
在评论中,我指出:
如果您重视自己的理智,请使用一致的名称。如果您被其他人的精神错乱所困扰,那么您必须指定/path/to/dir1 和/path/to/dir2 下的目录之间的映射,可能是通过一个文件(我们希望路径名不包含空格) !)。然后你可以这样做:while read src dst; do cp -fr $src $dst; done < directory-mapping-file。
回复的是:
啊,是的,我的理智。恐怕已经大部分消失了,这些子目录是客户名称。我的决定,但是一个我现在无法真正改变的旧决定。所以这似乎对我来说可以很好地使用映射文件。但如果你不介意,你能告诉我文件是什么样子的吗?
啊,是的,我很熟悉发现我在很久以前的时候并不完全清醒,我不得不忍受后果。
我想到的方案,假设路径名不包含空格,非常简单:
目录映射文件
/path/to/dir1/sub1 /path/to/dir2/subsub1
/path/to/dir1/sub2 /paht/to/dir2/semisub-2
即包含dir1下的子目录名称和dir2下的名称。
目录复制代码
然后你使用它的方式类似于这个(小心地做模糊适当的错误检查):
while read src tgt
do
[ ! -d "$src" ] && { echo "$0: Not a directory: $src" 1>&2; continue; }
[ ! -d "$tgt" ] && { echo "$0: Not a directory: $tgt" 1>&2; continue; }
echo "Mapping files under $src to $tgt"
(
if cd "$src"
then cp -rf . "$tgt"
else echo "$0: Oops! cd $src failed" 1>&2
fi
)
done < /path/to/dir1/directory-mapping-file
显然,您可以在任何方便的地方找到目录映射文件。请注意,除非您小心(如图所示)使用正确的相对名称,否则您最终可能会在目标目录下出现不需要的目录层次结构。绝对要试验并仔细检查脚本是否为您提供所需的内容。另请注意,cd 命令是在显式子 shell 中完成的(( ... ) 表示法。这将目录更改隔离到子 shell,这通常比在父 shell 中执行 cd 更有弹性. 如果来自cd 命令的错误消息足够,则不需要else 子句,您可以将其全部简化为:
cd "$src" && cp -rf . "$tgt"
请注意,我引用了这些名称;这可能是老式的 shell 脚本,但是如果您曾经更改为路径名包含空格的系统,如果您始终将名称用引号括起来,则更容易让脚本与各种 shell 一起正常工作。
一个很好的改进是允许文件中的 cmets 和空行:
sed -e 's/#.*//' -e '/^[ \t]*$/d' /path/to/dir1/directory-mapping-file |
while read src tgt
do
...as above...
done
请注意,\t 可能需要是一个实际的选项卡(但在 Markdown 中显示选项卡有点困难)。我有一个脚本,我称之为 nbncl(非空白、非注释行),它封装了所示 sed 命令的逻辑(尽管它实际上是一个非最小的 Perl 脚本)。使用它给出:
nbncl /path/to/dir1/directory-mapping-file |
while read src tgt
...as before...