File: shell

package info (click to toggle)
gnu-smalltalk 3.2.4-2.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 32,688 kB
  • ctags: 14,104
  • sloc: ansic: 87,424; sh: 22,729; asm: 8,465; perl: 4,513; cpp: 3,548; xml: 1,669; awk: 1,581; yacc: 1,357; makefile: 1,237; lisp: 855; lex: 843; sed: 258; objc: 124
file content (154 lines) | stat: -rwxr-xr-x 6,197 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#! /bin/sh
"exec" "gst" "-f" "$0" "$@"

"======================================================================
|
|   Example of starting a Smalltalk program from the shell
|
 ======================================================================"

" The first line above is parsed specially by GNU Smalltalk.  gst -f
| is similar to passing -aQ after the first argument, so the net result
| is that of executing
|
|    gst /path/to/this/script -aQ param1 param2 paramN
|
| Also, GNU Smalltalk sees five comments instead of the shell command
| `exec gst -f $0 "$@"'.
|
| Now here is the file juggler by Alexander Lazarevic, the first Smalltalk
| script known to me. <Alexander@Lazarevic.de>
|
| Usage: popoolate [inputdir] [pooldir]
|
| I assume everybody has this one kind of folder called temp, incoming,
| files or whatever. There is all the rubble you've downloaded from the
| web (and surprisingly much more). Once in a while you wade through
| all the files and delete the ones you think you don't need
| anymore. The rest stays in the folder and the folder grows and
| grows...
| This kind of folder is what popoolate expects as the inputdir
| parameter. Basically popoolate just copies the files from inputdir to
| pooldir, but in addition it creates subfolders in pooldir according
| to the filenames.

| For example I have a directory (in) where I have some snapshots of my
| son, some karaoke music and some other stuff. After using popoolate
| the folder in will be empty and the folder pool will have
| the following structure:

| in--Leon-0019.jpg     pool - l - leon  - leon-0019.jpg
|     Leon-0030.jpg                        leon-0020.jpg
|     PeSo-99.mp3                          leon10.jpg
|     World_9.pdf              p - peso  - peso-99.mp3
|     leon10.jpg                   pop   - pop10a.mp3
|     pop10a.mp3                           pop10b.mp3
|     pop10b.mp3                           pop10c.mp3
|     pop10c.mp3               w - world - world-1.pdf
|     world-1.pdf                          world_9.pdf
"

| error inputDir poolDir namePattern rightPattern |

PackageLoader fileInPackages: #('Regex').

error := [:message| stderr nextPutAll: message; nl.
		    ObjectMemory quit: 1].

Smalltalk arguments size ~= 2
   ifTrue: [error value: 'usage: popoolate [inputdir] [pooldir]'].
    
inputDir := Directory name: (Smalltalk arguments first).
inputDir isDirectory
   ifFalse: [error value: '"', inputDir name, '" is no directory!'].
inputDir isWriteable
   ifFalse: [error value: '"', inputDir name, '" is unwriteable!'].
inputDir isReadable
   ifFalse: [error value: '"', inputDir name, '" is unreadable!'].
inputDir isAccessible
   ifFalse: [error value: '"', inputDir name, '" is unaccessible!'].
    
poolDir := Directory name: (Smalltalk arguments last).
inputDir isDirectory
   ifFalse: [error value: '"', inputDir name, '" is no directory!'].
inputDir isWriteable
   ifFalse: [error value: '"', inputDir name, '" is unwriteable!'].
inputDir isAccessible
   ifFalse: [error value: '"', inputDir name, '" is unaccessible!'].

"Uncomment this to test....

#('a' 'noep' 'aa' 'n' 'Bnm' 'HjKlo') do:
   [:name|
      1 to: 300 do:
         [:num||file|
	    file := FileStream
		   open: '/tmp/in/', name, '-', num printString, '.tst'
		   mode: FileStream write.
	    file close]]
]."

namePattern := (
   '[~]',       "Not allowed anywhere in the filename"
   '|',
   '^[!._]',    "Not allowed at the beginning"
   '|',
   '^.*\\',     "Cut DOS path"
   '|',
   '\s[^.]*$')  "Cut trailing garbage after extension"

   asRegex.

"This pattern assumes that a (lowercase) filename belongs to a
 series of filenames and that it has a left and right side. The
 left side is the stem part and is the same for all filenames in
 the series. The right side consists of an index part and a file
 extension (in that order). This pattern tries to match the index
 part and file extension (right side), leaving the stem part (left
 side)."

rightPattern := (
   '(',                    "Index part might start with"
     '([_-])\d+',          "a _ or - and at least one digit"
   '|',                    "or"
   '(\d\d\d|\d\d|\d)',     "with exactly three, two or one
                            digit(s) as an index number"
   ')',
   '[a-z]?',               "Between index part and extension might be"
                           "a single letter"
   '\..*')                 "The extension is anything including
                            the first dot upto the end, eg. .pdf
                            but also .tex.gz"
   asRegex.
    
inputDir contents do:
   [:origname|| file | 
    file := inputDir at: origname.
    ((origname first = $. or: [file isDirectory]) or: [file isReadable not])
       ifTrue:  [stdout nextPutAll: 'Ignoring ', origname; nl]
       ifFalse: [| cleanname series slot seriesDir slotDir|
                 cleanname := origname asLowercase.
                 cleanname := cleanname copyReplacingAllRegex: namePattern with: ''.
                 series := cleanname copyReplacingAllRegex: rightPattern with: ''.
                 (series isEmpty or: [series = cleanname])
                    ifTrue:  [slot := 'single'.
                              series := nil.]
                    ifFalse: [series first isAlphaNumeric
                                ifTrue:  [slot := series first asString]
                                ifFalse: [slot := 'misc']].
                 slotDir := (poolDir directoryAt: slot).
                 slotDir exists
		    ifFalse: [Directory create: slotDir name.
                              stdout nextPutAll: slotDir name, ' created.';nl].
                 series = nil
                    ifTrue:  [seriesDir := slotDir]
                    ifFalse: [seriesDir := (slotDir directoryAt: series).
                              seriesDir exists
		              ifFalse: [Directory create: seriesDir name.
                                        stdout nextPutAll: seriesDir name, ' created.';nl]].
                 stdout nextPutAll: origname, ' -> ', (seriesDir nameAt: cleanname); nl.
                 file renameTo: '/', (seriesDir fullNameAt: cleanname).
                ]].
    ObjectMemory quit: 0.
    
!