find / -user $user -exec chown $newuid '{}' ;
-exec选项会针对每一个与条件比对相符的文件执行接下来的所有参数,直到分号为止。find命令里的{}意指替换找到的文件名称至命令。这样使用find代码很高,因为它会针对每一个文件或目录建立一个新的chown进程。可以替换成:
find / -user $user -print | xargs chown $newuid
#有GNU工具集可以:
find / -user $user -print0 | xargs --null chown $newuid
这样就把所有需要更改的文件传送至一个新的进程来处理,而不是很多个。
这里有个另外的问题,加入old-new-list里的数据这样:
juser 25 10
mrwizard 10 30
也就是说如果先变更juser,把juser的文件权限UID25变更为UID10以后,再变更mrwizard的时候问题就来了,程序会把之前所有的juser的文件当成mrwizard的文件。这时就牵扯到处理顺序问题,我们必须在25变成10之前,把10变成30。解决方法也简单,给所有的UID编号是没有任何地方使用过即可。
这里还剩最后一个小问题,就是find命令寻找用户的时候,注意我们问题的环境,目前是有两台服务器,find寻找用户的时候是有可能找不到另一台服务器用户的。需要作出处理。
再说一下我们解决这个问题时规避的一些真实世界的问题。最明显的是我们很可能也需要合并/etc/group文件。再者,任何一个大型的系统,都可能会出现文件拥有已不存在于/etc/passwd与/etc/group里的UID或GID值,寻找这里文件可以这样:
find / '(' -nouser -o -nogroup ')' -ls
这样做将产生所有这样的文件输出。可以使用管道进一步处理xargs chown...这样。
第三点是在改变文件的用户与组处理期间,文件系统绝对得静止。处理时不应该有任何其他活动发生,使系统处于单用户模式下root登录,且只能在系统物理console设备上完成这个任务。
最后就是效率问题,每个用户都需要跑一遍find是很不划算的,我们可以跑一遍来处理所有用户的文件,类似这样:
find / -ls | awk -f make-command.awk old-to-new.txt - > /tmp/commands/sh ... 在执行前先检查 /tmp/commands/sh ... sh / tmp/commands/sh
类似这样。先读取old-to-new.txt的旧换新UID变更,然后awk会针对每一个输出文件寻找是否有必须被更改,如果要更改则使用chown命令。
详细代码之类的略过吧,没特殊算法,都很简单。
第十二章拼写检查
最初的unix拼写检查原型为代码说一下:
prepare filename | #删除格式化命令
tr A-Z a-z | #大写转化为小写
tr -c a-z 'n' | #删除字母以外字符
sort | uniq |
comm -13 dictinary - #报告不再字典内的单词
comm命令是用以比较两个排序后的文件,并选定或拒绝两个文件里共同的行。-13选项是仅输出来自第二个文件(管道输入的内容)但不在第一个文件(字典)里的行。-1 不显示第一列(只在第一个文件出现的行)-2 不显示第二列(只在第2个文件出现的行)-3不显示第三列(两个文件都有的行)。










