Scripts - file and folder enumeration

And here's one to navigate through a home directory folder and change ownership of all folders to the home directory owner.

This script was required after the home directories got copied onto another server with a different operating system.

This works in Smalltalk 3.0x (I understand there are changes coming in File/Directory in 3.1)

 #! /usr/local/bin/gst  -f
 
 
 Object subclass: #DirNav
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'SG-Scripting'!

DirNav comment: 
'Shell scripting example in GNU-Smalltalk' !

!DirNav methodsFor: 'operation'!

enum_folders: dirname
    "Navigate a homes directory and update the permissons - name of home directory
     is the name of the account that owns the home folder"
    "The _pipe_ lines are commented for your safety. Uncomment the pipes to make the script active." 
   | homedir pipe shellCmd |
   (File exists: dirname) 
      ifFalse: [Transcript showCr: 'enum_folders. Path: ',dirname,' does not exist']
      ifTrue:  [
           " Note: Want to enumerate directory names. GST doesn't deliver . and .. so 
               avoid these based on path size"
           " Note: in GST 2.x allFilesMatching: does not return directories. Just files.
               fixed in GST 3.0"
           homedir := Directory name: dirname.
           "homedir allFilesMatching: '*' do: [ :file | "
           homedir filesMatching: '*' do: [ :file | 
              ((file isDirectory)  &  ((file name size) > (homedir name size)))
                ifTrue: [
                   shellCmd := 'chown -R "AD+%1:AD+domain admins" %2'
                      bindWith: (file stripPath) with: (file name). 
                   Transcript showCr: 'About to run command: ',shellCmd.
                   "pipe := FileStream popen: shellCmd dir: FileStream read."
                   shellCmd := 'chmod -R 700 ', file name. 
                   Transcript showCr: 'About to run command: ',shellCmd.
                   "pipe := FileStream popen: shellCmd dir: FileStream read."
                   ]
      ].    ].
   ! !

| dirnav |
dirnav := DirNav new.
dirnav init.
dirnav enum_folders: '/devel/testdata' !

I haven't tested it but I think it should work in 3.1 too.

Also, opening pipes like that is going to leak a lot of file descriptors. I think you can start a process that reaps them, like.

[|pipe|
   pipe := FileStream popen: shellCmd dir: FileStream read.
   [pipe close] fork
] value

(putting everything in a separate block to make a separate variable for each pipe).

User login