In this week i wrote a emacs program and tutorial that does archiving a website for offline reading. (See http://xahlee.org/emacs/make_download_copy.html )
In the process, i ran into a problem with the unix “cp” utility. I've been a unix admin for Solaris during 1998-2004. Even the first time i learned about cp, i noticed some pecularity. But only today, i thought about it and wrote it out exactly what's going on. Here's a excerpt from my emacs tutorial above regarding the issue. ------------------ Copying a bunch of directories seems a trivial operation, but it actually took me a couple hours to arrive at the final code, due to the exact requirement of directory paths, and the unix “cp” tool's lack of precision and flexibility. Originally, i thought the code would be something simple like several “(shell-command (concat "cp -R " fromDir " " toDir))”, one for each source dir, where fromDir and toDir are full paths. However, it turns out the problem is slightly more complex. Suppose the source dir is “/Users/xah/web/emacs” and dest dir is “/ Users/xah/web/diklo/xahtut/emacs” and i want all branches under the source dir copied into the dest dir. If you do “cp -R /Users/xah/web/emacs /Users/xah/web/diklo/xahtut/ emacs” with both xahtut and xahtut/emacs doesn't exist, then this error results: “cp: /Users/xah/web/diklo/xahtut/emacs: No such file or directory”. If you do “cp -R /Users/xah/web/emacs /Users/xah/web/diklo/xahtut/ emacs” with xahtut/emacs exists, then you got “/Users/xah/web/diklo/ xahtut/emacs/emacs”, which is not what i want. If you do “cp -R /Users/xah/web/emacs /Users/xah/web/diklo/xahtut” with xahtut doesn't exist, it results in all branches of emacs in xahtut, which is wrong. Only when you do “cp -R /Users/xah/web/emacs /Users/xah/web/diklo/ xahtut” with xahtut exists, you get the correct result with the new dir “/Users/xah/web/diklo/xahtut/emacs” having all branches of the original dir. So, the solution is to first create all the parent dirs of the dest dir, but without the dest dir node itself. Then, do a cp to the first parent of dest dir. Directories are abstractly a tree. Copying directories is like grafting a tree from one branch into another branch. To begin, we are given two spec: the source node and a destination node. The source node by definition is a existing node (i.e. existing dir or file), otherwise the copying won't make sense. However, the destination spec can be a node that doesn't exist, or its parents doesn't exist, or several levels of parents doesn't exist. When the destination spec has missing nodes, we can consider creating them as part of the grafting process, or we can consider it as a error. The unix “cp” tool's behavior is mathematically inconsistent. When the destination node exist, the source node will become new children of destination node. When the destination node does not exist (but its parent exists), “cp” will create the node, and copy only the children of the source node to it. When the destination node doesn't exist and its parent doesn't exist neither, then “cp” considers it a error. --------------- Related readings: • The Nature of the “Unix Philosophy” http://xahlee.org/UnixResource_dir/writ/unix_phil.html Xah ∑ http://xahlee.org/ ☄ -- http://mail.python.org/mailman/listinfo/python-list