pyKook Users' Guide
Preface
pyKook is a software build tool such as Make, Rake, Ant, SCons or Cook. It is implemented in Python and runs any platform Python support. Basic command (copy, move, rename, mkdir, ...) is also implemented in Python and allows you to execute platform-depended command.
pyKook liken build process to cooking. Input file is called 'ingredient', output is 'product', task is 'recipe', build file is 'cookbook'. pyKook generates products from ingredients according to recipes. You describe products, ingredients, and recipes in cookbook.
Features:
- Impremented in pure Rython and runs any platform which Python supports.
- Input file (called 'cookbook') is named 'Kookbook.py', which is equivarent to 'Makefile' of Make or 'build.xml' of Ant.
- Cookbook's format is pure Python. You can write any Python code in kookbook.
- Support command-line scripting framework.
Caution! pyKook is currently under experimental. It means that the design and specification of pyKook may change without prior notice.
Table of Contents
Cookbook
This sectipn describes how to write cookbook.
Recipes
Cookbook should contains some recipes. Each recipes are described with function and function decorators.
@recipe
decorator represents that this is a recipe definition. If function is not decorated by@recipe
, it is not regarded as recipe.@product()
decorator represents filename which is generated by the recipe. This takes only an argument.@ingreds()
decorator represents filenames which are required to generate product. This can take several arguments.- function
file_xxx()
represents how to generate the product from ingredients. It is called as recipe function. Recipe function name should be start with 'file_' prefix if it generates file product. - function description is regarded as recipe description.
In cookbook, some helper functions provided by pyKook are available. For exaple, function 'system()
' invokes OS-depend command. See References for details about helper functions.
The following is an example of recipe definitions in cookbook.
# product "hello" depends on "hello.o". @recipe @product("hello") @ingreds("hello.o") def file_hello(c): """generates hello command""" # recipe description system("gcc -g -o hello hello.o") # product "hello.o" depends on "hello.c" and "hello.h". @recipe @product("hello.o") @ingreds("hello.c", "hello.h") def file_hello_o(c): """compile 'hello.c' and 'hello.h'""" # recipe description system("gcc -g -c hello.c")
The following is an example of invoking pykook
command(*1). Command-line option '-l
' shows recipes which have description. It means that recipes which have description are public recipes. Command-line option '-L
' shows all recipes.
sh> pykook -l Properties: Task recipes: File recipes: hello : generates hello command hello.o : compile 'hello.c' and 'hello.h' (Tips: you can set 'kook_default_product' variable in your kookbook.) sh> pykook hello ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o
pyKook checks both timestamps and contents of files (= products, ingredients).
- If product is older than ingredients, that recipe will be executed.
- If product is newer than or have the same timestamp as ingredients, that recipe will not be executed.
- If recipe of ingredient is executed but content of ingredient is not changed, then recipe of product will not be executed and product will be 'touched'.
- If you specify command-line option '
-F
', these rules are ignored and all recipes are executed forcedly.
sh> pykook hello # 1st time ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o sh> pykook hello # 2nd time # nothing, because hello is already created. sh> touch hello.c # touch hello.c sh> pykook hello # 3rd time ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c # compiled, because hello.c is newer than hello.o. ### * hello (recipe=file_hello) $ touch hello # skipped # skipped, because content of hello.o is not changed. sh> pykook -F hello # 4th time (forcedly) ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o
- (*1)
- pyKook also provides
kk
command which is equivarent topykook
, becausepykook
is too long to type many times :)
Product and Ingredients
Product and ingredient names are referable as property of recipe function's argument.
- Property 'c.product' represents product.
- Property 'c.ingreds' represents ingredients.
- Property 'c.ingred' represents the first item of ingredients (= c.ingreds[0]).
c.product
and c.ingreds
# product "hello" depends on "hello.o". @recipe @product("hello") @ingreds("hello.o") def file_hello(c): """generates hello command""" system("gcc -g -o %s %s" % (c.product, c.ingred)) # or system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) # or system(c%"gcc -g -o $(product) $(ingreds[0])") # product "hello.o" depends on "hello.c" and "hello.h". @recipe @product("hello.o") @ingreds("hello.c", "hello.h") def file_hello_o(c): """compile 'hello.c' and 'hello.h'""" system("gcc -g -c %s" % c.ingred) # or system("gcc -g -c %s" % c.ingreds[0]) # or system(c%"gcc -g -c $(ingred)")
sh> pykook hello ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o
pyKook provides convenience way to embed variables into string literal. For example, the followings are equivarent.
system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) # or c.ingred system(c%"gcc -g -o $(product) $(ingreds[0])") # or $(ingred)
You can write local or global variables in $()
as well as product
or ingreds
.
CC = 'gcc' # global variable @recipe @product("hello") @ingreds("hello.o") def file_hello(c): CFLAGS = '-g -Wall' # local variable system(c%"$(CC) $(CFLAGS) -o $(product) $(ingreds[0])")
Specific recipe and generic recipe
Specific recipe is a recipe which is combined to a certain file. Product name of specific recipe is a concrete file name.
Generic recipe is a recipe which is combined to a pattern of file name. Product name of generic recipe is a pattern with metacharacter or regular expression.
pyKook converts file name pattern into regular expression. For example:
'*.o'
will be coverted intor'^(.*?)\.o$'
.'*.??.txt'
will be converted into tor'^(.*?)\.(..)\.txt$'
.
Matched strings with metacharacter ('*' or '?') are accessable by $(1)
, $(2)
, ... in @ingreds()
decorator.
## specific recipe @recipe @product("hello") @ingreds("hello.o") def file_hello(c): """generates hello command""" system(c%"gcc -g -o $(product) $(ingred)") # or system("gcc -g -o %s %s" % (c.product, c.ingred)) # or system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) ## generic recipe @recipe @product("*.o") # or @product(re.compile(r'^(.*?)\.o$')) @ingreds("$(1).c", "$(1).h") def file_ext_o(c): """compile '*.c' and '*.h'""" system(c%"gcc -g -c $(1).c") # or system("gcc -g -c %s.c" % c.m[1]) # or system("gcc -g -c %s" % c.ingred)
sh> pykook -l Properties: Task recipes: File recipes: hello : generates hello command *.o : compile '*.c' and '*.h' (Tips: you can set 'kook_default_product' variable in your kookbook.) sh> pykook hello ### ** hello.o (recipe=file_ext_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o
It is able to specify regular expression instead of filename pattern. For example, @product(re.compile(r'^(.*)\.o$'))
is available as product instead of @product('*.o')
. Grouping in regular expression is referable by $(1)
, $(2)
, ... in the same way.
Specific recipe is prior to generic recipe. For example, recipe 'hello.o' is used and recipe '*.o' is not used to generate 'hello.o' when target product is 'hello.o' in the following example.
## When target is 'hello.o', this specific recipe will be used. @recipe @product("hello.o") @ingreds("hello.c") def file_hello_o(c): system(c%"gcc -g -O2 -o $(product) $(ingred)") ## This generic recipe will not be used, because specific recipe ## is prior than generic recipe. @recipe @product("*.o") @ingreds("$(1).c", "$(1).h") def file_o(c): system(c%"gcc -g -o $(product) $(ingred)")
Conditional Ingredients
There may be a case that ingredient file exists or not. For example, product 'foo.o' depends on 'foo.c' and 'foo.h', while product 'bar.o' depends only on 'bar.c'.
In this case, you can use if_exists()
helper function which resolve the problem. For example, when if_exists("hello.h")
is specified in @ingreds()
, pyKook detect dependency as following.
- If file 'hello.h' exists, product 'hello.o' depends on ingredients 'hello.c' and 'hello.h'.
- If file 'hello.h' doesn't exist, product 'hello.o' depends on only 'hello.c'.
if_exists()
is useful especially when used with generic recipes.
if_exists()
## specific recipe @recipe @product("hello") @ingreds("hello.o") def file_hello(c): """generates hello command""" system(c%"gcc -g -o $(product) $(ingred)") # or system("gcc -g -o %s %s" % (c.product, c.ingred)) # or system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) ## generic recipe @recipe @product("*.o") # or @product(re.compile(r'^(.*?)\.o$')) @ingreds("$(1).c", if_exists("$(1).h")) def file_hello_o(c): """compile '*.c' and '*.h'""" system(c%"gcc -g -c $(1).c") # or system("gcc -g -c %s.c" % c.m[1]) # or system("gcc -g -c %s" % c.ingred)
sh> pykook hello ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o
File Recipe and Task Recipe
In pyKook, there are two kind of recipe.
- File recipe
- File recipe is a recipe which generates a file. In the other word, product of recipe is a file. If product is not generated, recipe execution will be failed.
- Task recipe
- Task recipe is a recipe which is not aimed to generate files. For example, task recipe 'clean' will remove '*.o' files and it doesn't generate any files.
Here is a matrix table of recipe kind.
Specific recipe | Generic recipe | |
File recipe | Specific file recipe | Generic file recipe |
Task recipe | Specific task recipe | Generic task recipe |
pyKook determines recipe kind ('file' or 'task') according the following simple rule:
- File recipe should start with 'file_' prefix.
- Task recipe may stat with 'task_' prefix, or NOT decorated by @product().

In the following example, task recipe clean
is a recipe to delete '*.o' files and is not combined to file 'clean'. Also task recipe all
is a recipe to call recipe of 'hello' and is not combined to file 'all'.
## file recipe @recipe @product("hello") @ingreds("hello.o") def file_hello(c): """generates hello command""" system(c%"gcc -g -o $(product) $(ingred)") # or system("gcc -g -o %s %s" % (c.product, c.ingred)) # or system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) ## file recipe @recipe @product("*.o") # or @product(re.compile(r'^(.*?)\.o$')) @ingreds("$(1).c", if_exists("$(1).h")) def file_ext_o(c): """compile '*.c' and '*.h'""" system(c%"gcc -g -c $(1).c") # or system("gcc -g -c %s.c" % c.m[1]) # or system("gcc -g -c %s" % c.ingred) ## task recipe @recipe def clean(c): """remove '*.o' files""" rm_f("*.o") ## task recipe ## (in order to avoid to overwrite 'all()' built-in function, ## add 'task_' prefix to function name.) @recipe @ingreds("hello") def task_all(c): """create all files""" pass
'pykook -l
' will display task recipes and file recipes.
sh> pykook -l Properties: Task recipes: clean : remove by-products all : cook all products File recipes: hello : generates hello command *.o : compile '*.c' and '*.h' (Tips: you can set 'kook_default_product' variable in your kookbook.) sh> pykook all ### *** hello.o (recipe=file_ext_o) $ gcc -g -c hello.c ### ** hello (recipe=file_hello) $ gcc -g -o hello hello.o ### * all (recipe=task_all) sh> pykook clean ### * clean (recipe=clean) $ rm -f *.o sh> ls -F Kookbook.py hello* hello.c hello.h
pyKook have several well-known task name. Task recipes which product name is in the following list will be got pubilic automatically. For example, if you have defined 'all' task recipe, it will be displayed by 'pykook -l
' even when recicpe function doesn't have any description.
- all
- create all products
- clean
- remove by-products
- clear
- remove all products and by-products
- deploy
- deploy products
- config
- configure
- setup
- setup
- install
- install products
- test
- do test
Default Product
If you set kook_default_product
variable, pykook command will use it as default product.
## global variables basename = 'hello' command = basename kook_default_product = 'all' # default product name ## file recipe @recipe @product(command) @ingreds(basename + ".o") def file_hello(c): """generates hello command""" system(c%"gcc -g -o $(product) $(ingred)") # or system("gcc -g -o %s %s" % (c.product, c.ingred)) # or system("gcc -g -o %s %s" % (c.product, c.ingreds[0])) ## file recipe @recipe @product("*.o") # or @product(re.compile(r'^(.*?)\.o$')) @ingreds("$(1).c", if_exists("$(1).h")) def file_ext_o(c): """compile '*.c' and '*.h'""" system(c%"gcc -g -c $(1).c") # or system("gcc -g -c %s.c" % c.m[1]) # or system("gcc -g -c %s" % c.ingred) ## task recipe @recipe def clean(c): """remove '*.o' files""" rm_f("*.o") ## task recipe @recipe @ingreds(command) def task_all(c): """create all files""" pass
If you specify kook_default_product
, you can omit target product name in commad-line.
sh> pykook # you can omit target product name ### *** hello.o (recipe=file_ext_o) $ gcc -g -c hello.c ### ** hello (recipe=file_hello) $ gcc -g -o hello hello.o ### * all (recipe=task_all)
Properties
Property is a global variable which value can be overwrited in command-line option.
Property is defined by prop()
function. It takes property name and default value as arguments.
## global variables (not properties) basename = 'hello' kook_default_product = 'all' ## properties CC = prop('CC', 'gcc') CFLAGS = prop('CFLAGS', '-g -O2') command = prop('command', basename) ## file recipes @recipe @product(command) @ingreds(basename + ".o") def file_command(c): system(c%"$(CC) $(CFLAGS) -o $(product) $(ingred)") @recipe @product("*.o") @ingreds("$(1).c", if_exists("$(1).h")) def file_ext_o(c): system(c%"$(CC) $(CFLAGS) -c $(ingred)") ## task recipes @recipe def clean(c): """remove '*.o' files""" rm_f("*.o") @recipe @ingreds(command) def task_all(c): pass
Properties are shown when command-line option '-l' is specified.
sh> pykook -l Properties: CC : 'gcc' CFLAGS : '-g' command : 'hello' Task recipes: clean : remove '*.o' files all : cook all products File recipes: (Tips: you can set 'kook_default_product' variable in your kookbook.)
If you don't specify any property values in command-line, default values are used.
sh> pykook all ### *** hello.o (recipe=file_ext_o) $ gcc -g -c hello.c ### ** hello (recipe=file_command) $ gcc -g -o hello hello.o ### * all (recipe=task_all)
If you specify property values in command-line, that values are used instead of default values.
sh> pykook --command=foo --CFLAGS='-g -O2 -Wall' all ### *** hello.o (recipe=file_ext_o) $ gcc -g -O2 -Wall -c hello.c ### ** foo (recipe=file_command) $ gcc -g -O2 -Wall -o foo hello.o ### * all (recipe=task_all)
Property file is another way to specify properties. If you have create property file 'Properties.py' in current directory, pykook command reads it and set property values automatically.
CFLAGS = '-g -O2 -Wall' command = 'foo'
Don't forget to write prop('prop-name', 'default-value')
in your cookbook even when property file exists.
Result of pykook -l
will be changed when property file exists.
sh> pykook -l Properties: CC : 'gcc' CFLAGS : '-g -O2 -Wall' command : 'foo' Task recipes: clean : remove '*.o' files all : cook all products File recipes: (Tips: you can override properties with '--propname=propvalue'.)
Materials
There is an exception in any case. Assume that you have a file 'optparse.o' which is supplied by other developer and no source. pyKook will try to find 'optparse.c' and failed in the result.
Using 'kook_materials' variable, you can tell pyKook that 'optparse.o' is not a product.
## global variables (not properties) basename = 'hello' kook_default_product = 'all' kook_materials = ['optparse.o', ] # specify materials ## properties CC = prop('CC', 'gcc') CFLAGS = prop('CFLAGS', '-g -O2') command = prop('command', basename) ## recipes @recipe @product(command) @ingreds("hello.o", "optparse.o") def file_command(c): system(c%"$(CC) $(CFLAGS) -o $(product) $(ingreds)") @recipe @product("*.o") @ingreds("$(1).c", if_exists("$(1).h")) def file_ext_o(c): system(c%"$(CC) $(CFLAGS) -c $(ingred)") @recipe @ingreds(command) def task_all(c): pass
In this example:
- 'hello.o' will be compiled from 'hello.c'.
- 'optparse.o' will not be compiled because it is specified as material.
sh> pykook all ### *** hello.o (recipe=file_ext_o) # only hello.o is compiled $ gcc -g -O2 -c hello.c ### ** hello (recipe=file_command) $ gcc -g -O2 -o hello hello.o optparse.o ### * all (recipe=task_all)
Command-line options for recipe
You can specify command-line options for certain recipes by @spices()
decorator.
## global variables (not properties) basename = 'hello' kook_default_product = 'all' kook_materials = ['optparse.o', ] # specify materials ## properties CC = prop('CC', 'gcc') CFLAGS = prop('CFLAGS', '-g -O2') command = prop('command', basename) ## recipes @recipe @product(command) @ingreds("hello.o", "optparse.o") def file_command(c): system(c%"$(CC) $(CFLAGS) -o $(product) $(ingreds)") @recipe @product("*.o") @ingreds("$(1).c", if_exists("$(1).h")) def file_ext_o(c): system(c%"$(CC) $(CFLAGS) -c $(ingred)") @recipe @ingreds(command) def all(c): pass @recipe @ingreds(command) @spices("-d dir: directory to install (default '/usr/local/bin')", "--command=command: command name (default '%s')" % command) def install(c, *args, **kwargs): opts, rests = kwargs, args dir = opts.get('d', '/usr/local/bin') # get option value cmd = opts.get('command', command) # get option value system(c%"sudo cp $(command) $(dir)/$(cmd)") # or use 'install' command
Command-line options of recipes are displayed by '-l' or '-L' option.
sh> pykook -l Properties: CC : 'gcc' CFLAGS : '-g -O2' command : 'hello' Task recipes: all : cook all products install : install product -d dir directory to install (default '/usr/local/bin') --command=command command name (default 'hello') File recipes: kook_default_product: all (Tips: 'c%"gcc $(ingreds[0])"' is more natural than '"gcc %s" % c.ingreds[0]'.)
You can specify command-line options for the recipe.
sh> pykook install -d /opt/local/bin --command=hellow ### * install (recipe=task_install) $ sudo cp hello /opt/local/bin/hellow Password: *******
This feature can replace many small scripts with pyKook.
The following is an example to show styles of @spices
arguments.
@recipe @spices("-h: help", # short opts (no argument) "-f file: filename", # short opts (argument required) "-d[N]: debug level", # short opts (optional argument) "--help: help", # long opts (no argument) "--file=file: filename", # long opts (argument required) "--debug[=N]: debug level", # long opts (optional argument) ) def echo(c, *args, **kwargs): """test of @spices""" opts, rests = kwargs, args print "opts:", repr(opts) print "rests:", repr(rests)
sh> pykook -L Properties: Task recipes: echo : test of @spices -h help -f file filename -d[N] debug level --help help --file=file filename --debug[=N] debug level File recipes: (Tips: you can override properties with '--propname=propvalue'.) sh> pykook echo -f hello.c -d99 --help --debug AAA BBB ### * echo (recipe=task_echo) opts: {'debug': True, 'help': True, 'd': 99, 'f': 'hello.c'} rests: ('AAA', 'BBB')
Other features
Command-line Scripting Framework
pyKook supports to create command-line script.
The points are:
- Add '#!/usr/bin/env pykook -X' as first line of script (shebang).
- Add 'kook_desc = "..script description.."'.
- Define specific task recipes which are regarded as sub-command.
#!/usr/bin/env pykook -X from kook.utils import CommandOptionError kook_desc = "example script to show pyKook's CLI framework feature" @recipe def hello(c): """prints hello world""" # description of sub-command echo("Hello world!") @recipe @spices("-u user: username") def sweet(c, *args, **kwargs): """prints words of love""" # description of sub-command user = kwargs.get('u', "you") # or raise CommandOptionError("sweet: required '-u username' option.") echo("I love %s!" % user)
### Don't forget to make script executable! sh> chmod a+w hello ### Show help sh> ./hello -h hello - example script to show pyKook's CLI framework sub-commands: hello : prints hello world sweet : prints words of love (Type 'hello -h subcommand' to show options of sub-commands.) ### Show help for each sub-command sh> ./hello -h sweet hello sweet - prints words of love -u user : username ### Invoke sub-command sh> ./hello hello Hello world! sh> ./hello sweet I love you! sh> ./hello sweet -u Haruhi I love Haruhi!
Debug mode
Command-line option -D
or -D2
turn on debug mode and debug message will be displayed. -D2
is higher debug level than -D
.
-D
sh> pykook -D hello *** debug: + begin hello *** debug: ++ begin hello.o *** debug: +++ material hello.c *** debug: +++ material hello.h *** debug: ++ create hello.o (recipe=file_hello_o) ### ** hello.o (recipe=file_hello_o) $ gcc -g -c hello.c *** debug: ++ end hello.o (content changed) *** debug: + create hello (recipe=file_hello) ### * hello (recipe=file_hello) $ gcc -g -o hello hello.o *** debug: + end hello (content changed)
Short command
pyKook provides kk
command which is the same as pykook
command, because pykook
is too long to type many times :)
sh> kk all # this is more confortable to type than pykook :)
Invoke Recipes Forcedly
Command-line option '-F' invokes recipes forcedly. In the other words, timestamp of files are ignored when '-F' is specified.
Nested Array
You can specify not only filenames but also list of filenames as ingredient @ingreds()
. pyKook flatten arguments of @ingreds()
automatically.
from glob import glob sources = glob("*.c") objects = [ s.replace(".c", ".o") for s in sources ] @recipe @product("hello") @ingreds(objects) # specify list of filenams def file_hello(c): system(c%"gcc -o $(product) $(ingreds)") # expanded to filenames @recipe @product("*.o") @ingreds("$(1).c") def file_ext_o(c): sysytem(c%"gcc -c $(ingred)")
Trouble Shooting
xxx: product not created (in file_xxx())
Q: I got the "xxx: product not created (in file_xxx())." error.
.A: You may define file recipe instead of task recipe. Don't specify '@product()' if you want to define task recipe.
## This will cause error @recipe @product("clean") def clean(c): #=> KookRecipeError: clean: product not created (in file_clean()). rm_f("*.o") ## Don't specify @product() @recipe def clean(c): #=> ok rm_f("*.o") ## Or add 'task_' prefix to function name @recipe @product("clean") def task_clean(c): #=> almost equivarent to above recipe rm_f("*.o")
*.c: can't find any recipe to produce.
Q: I got the "*.c: can't find any recipe to produce." error.
A: Use "$(1).c" instead of "*.c" in @ingreds() argument.
## This will cause error because "*.c" is used in ingredients. @recipe @product("*.o") @ingreds("*.c") #=> KookRecipeError: *.c: can't find any recipe to produce. def file_ext_o(c): system(c%"gcc -c $(ingred)") ## Use "$(1).c" instead of "*.c" @recipe @product("*.o") @ingreds("$(1).c") #=> ok def file_ext_o(c): system(c%"gcc -c $(ingred)")
sh: line 1: ingred: command not found
Q: I got the "sh: line 1: ingred: command not found" error.
A: Add "c%" at the beginning of command string.
## "c%" is forgetten @recipe @product("*.o") @ingreds("$(1).c") def file_ext_o(c): system("gcc -c $(ingred)") #=> KookCommandError: sh: line 1: ingred: command not found" error. ## Don't forget to add "c%" if you want to use "$()". @recipe @product("*.o") @ingreds("$(1).c") def file_ext_o(c): system(c%"gcc -c $(ingred)")
References
Filesystem Functions
The following functions are available in recipe.
- system(cmmand-string)
-
Execute command-string. If command status is not zero then exception is raised.
system("gcc hello.c")
- system_f(command-string)
- Execute command-string. Command statuis is ignored.
- echo(string)
-
Echo string. Newline is printed.
echo("OK.")
- echo_n(string)
-
Echo string. Newline is not printed.
echo_n("Enter your name: ")
- cd(dir)
-
Change directory. Return current directory.
cwd = cd("build") ... cd(cwd) # back to current directry
- chdir(dir)
-
Change current directory temporary. If this is used with Python's with-statement, current directory will be backed automatically.
with chdir("build") as d: ... # into "build" directory # back to current directry automatically
- mkdir(path)
-
Make directory.
mkdir("lib")
- mkdir_p(path)
-
Make directory. If parent directory is not exist then it is created automatically.
mkdir_p("foo/bar/baz")
- rm(path[, path2, ...])
-
Remove files.
rm('*.html', '*.txt')
- rm_r(path[, path2, ...])
-
Remove files or directories recursively.
rm_r('*')
- rm_f(path[, path2, ...])
-
Remove files forcedly. No errors reported even if path doesn't exist.
rm_f('*.html', '*.txt')
- rm_rf(path[, path2, ...])
-
Remove files or directories forcedly. No errors reported even if path doesn't exist.
rm_rf('*')
- touch(path[, path2, ...])
-
Touch files or directories. If path doesn't exist then empty file is created.
touch('*.c')
- cp(file1, file2)
-
Copy file1 to file2.
cp('foo.txt', 'bar.txt')
- cp(file, file2, ..., dir)
-
Copy file to dir.
cp('*.txt', '*.html', 'dir')
- cp_r(path1, path2)
-
Copy path1 to path2 recursively.
cp_r('dir1', 'dir2')
- cp_r(path, path2, ..., dir)
-
Copy path to dir recursively. Directory dir must exist.
cp_r('lib', 'doc', 'test', 'dir')
- cp_p(file1, file2)
-
Copy file1 to file2. Timestams is preserved.
cp_p('foo.txt', 'bar.txt')
- cp_p(file, file2, ..., dir)
-
Copy file to dir. Timestams is preserved. Directory dir must exist.
cp_p('*.txt', '*.html', 'dir')
- cp_pr(path1, path2)
-
Copy path1 to path2 recursively. Timestams is preserved.
cp_pr('lib', 'lib.bkup')
- cp_pr(path, path2, ..., dir)
-
Copy path to dir recursively. Directory dir must exist. Timestams is preserved.
cp_pr('lib/**/*.rb', 'test/**/*.rb', 'tmpdir')
- mv(file1, file2)
-
Rename file1 to file2.
mv('foo.txt', 'bar.txt')
- mv(path, path2, ..., dir)
-
Move path to dir.
mv('lib/*.rb', 'test/*.rb', 'tmpdir')
- store(path, path2, ..., dir)
-
Copy path (files or directories) to dir with keeping path-structure.
store("lib/**/*.py", "doc/**/*.{html,css}", "dir") ## ex. ## "lib/kook/__init__.py" is copied into "dir/lib/kook/__init__.py" ## "lib/kook/utils.py" is copied into "dir/lib/kook/utils.py" ## "lib/kook/main.py" is copied into "dir/lib/kook/main.py" ## "doc/users-guide.html" is copied into "dir/doc/users-guide.html" ## "doc/docstyle.css" is copied into "dir/doc/docstyle.css"
- store_p(path, path2, ..., dir)
-
Copy path (files or directories) to dir with keeping path-structure. Timestamp is preserved.
store_p("lib/**/*.py", "doc/**/*.html", "dir")
- edit(path, path2, ..., by=replacer)
-
Edit file content. Keyword argument 'by' should be a callable to edit content, or list of tuples of replacing pattern and string.
## edit by list of regular expression and string replacer = [ (r'\$Release\$', "1.0.0"), (r'\$Copyright\$', "copyright(c) 2008 kuwata-lab.com"), ] edit("lib/**/*.py", "doc/**/*.{html,css}", by=replacer) ## edit by function def replacer(s): s = s.replace('0.0.3', "1.0.0", s) s = s.replace('copyright(c) 2008-2009 kuwata-lab.com all rights reserved.', "copyright(c) 2008 kuwata-lab.com", s) return s edit("lib/**/*.py", "doc/**/*.{html,css}", by=replacer)
The above functions can take lists or tuples as file or directory names. (If argument is list or tuple, it is flatten by kook.utils.flatten()
.)
For example, the following code is available.
## copy all files into dir files = ['file1.txt', 'file2.txt', 'file3.txt'] cp(files, 'dir')
The following file pattern is available.
*
- Matches sequence of any character.
?
- Matches a character.
{a,b,c}
- Matches a or b or c.
**/
- Matches directory recursively.