ipy_fsops.py
245 lines
| 6.5 KiB
| text/x-python
|
PythonLexer
vivainio
|
r851 | """ File system operations | |
Contains: Simple variants of normal unix shell commands (icp, imv, irm, | |||
imkdir, igrep). | |||
Some "otherwise handy" utils ('collect' for gathering files to | |||
~/_ipython/collect, 'inote' for collecting single note lines to | |||
~/_ipython/note.txt) | |||
Mostly of use for bare windows installations where cygwin/equivalent is not | |||
installed and you would otherwise need to deal with dos versions of the | |||
commands (that e.g. don't understand / as path separator). These can | |||
do some useful tricks on their own, though (like use 'mglob' patterns). | |||
Not to be confused with ipipe commands (ils etc.) that also start with i. | |||
""" | |||
Brian Granger
|
r2027 | from IPython.core import ipapi | |
Brian Granger
|
r2205 | from IPython.core.error import TryNext | |
Brian Granger
|
r2027 | ip = ipapi.get() | |
vivainio
|
r851 | ||
import shutil,os,shlex | |||
from IPython.external import mglob | |||
vivainio
|
r964 | from IPython.external.path import path | |
Brian Granger
|
r2205 | from IPython.core.error import UsageError | |
Brian Granger
|
r2022 | import IPython.utils.generics | |
vivainio
|
r851 | ||
def parse_args(args): | |||
""" Given arg string 'CMD files... target', return ([files], target) """ | |||
tup = args.split(None, 1) | |||
if len(tup) == 1: | |||
vivainio
|
r860 | raise UsageError("Expected arguments for " + tup[0]) | |
vivainio
|
r851 | ||
tup2 = shlex.split(tup[1]) | |||
flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] | |||
if not flist: | |||
vivainio
|
r860 | raise UsageError("No files found:" + str(tup2[0:-1])) | |
vivainio
|
r851 | return flist, trg | |
def icp(ip,arg): | |||
""" icp files... targetdir | |||
Copy all files to target, creating dirs for target if necessary | |||
icp srcdir dstdir | |||
Copy srcdir to distdir | |||
""" | |||
import distutils.dir_util | |||
fs, targetdir = parse_args(arg) | |||
vivainio
|
r860 | if not os.path.isdir(targetdir) and len(fs) > 1: | |
vivainio
|
r851 | distutils.dir_util.mkpath(targetdir,verbose =1) | |
for f in fs: | |||
vivainio
|
r860 | if os.path.isdir(f): | |
shutil.copytree(f, targetdir) | |||
else: | |||
shutil.copy2(f,targetdir) | |||
vivainio
|
r851 | return fs | |
Brian Granger
|
r2205 | ip.define_alias("icp",icp) | |
vivainio
|
r851 | ||
def imv(ip,arg): | |||
""" imv src tgt | |||
Move source to target. | |||
""" | |||
fs, target = parse_args(arg) | |||
if len(fs) > 1: | |||
assert os.path.isdir(target) | |||
for f in fs: | |||
shutil.move(f, target) | |||
return fs | |||
Brian Granger
|
r2205 | ip.define_alias("imv",imv) | |
vivainio
|
r851 | ||
def irm(ip,arg): | |||
""" irm path[s]... | |||
Remove file[s] or dir[s] path. Dirs are deleted recursively. | |||
""" | |||
vivainio
|
r860 | try: | |
paths = mglob.expand(arg.split(None,1)[1]) | |||
except IndexError: | |||
raise UsageError("%irm paths...") | |||
vivainio
|
r851 | import distutils.dir_util | |
for p in paths: | |||
print "rm",p | |||
if os.path.isdir(p): | |||
distutils.dir_util.remove_tree(p, verbose = 1) | |||
else: | |||
os.remove(p) | |||
Brian Granger
|
r2205 | ip.define_alias("irm",irm) | |
vivainio
|
r851 | ||
def imkdir(ip,arg): | |||
""" imkdir path | |||
Creates dir path, and all dirs on the road | |||
""" | |||
import distutils.dir_util | |||
targetdir = arg.split(None,1)[1] | |||
distutils.dir_util.mkpath(targetdir,verbose =1) | |||
Brian Granger
|
r2205 | ip.define_alias("imkdir",imkdir) | |
vivainio
|
r851 | ||
def igrep(ip,arg): | |||
""" igrep PAT files... | |||
Very dumb file scan, case-insensitive. | |||
e.g. | |||
igrep "test this" rec:*.py | |||
""" | |||
elems = shlex.split(arg) | |||
dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) | |||
res = [] | |||
for f in fs: | |||
found = False | |||
for l in open(f): | |||
if pat.lower() in l.lower(): | |||
if not found: | |||
print "[[",f,"]]" | |||
found = True | |||
res.append(f) | |||
print l.rstrip() | |||
return res | |||
Brian Granger
|
r2205 | ip.define_alias("igrep",igrep) | |
vivainio
|
r851 | ||
def collect(ip,arg): | |||
""" collect foo/a.txt rec:bar=*.py | |||
Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, | |||
likewise | |||
Without args, try to open ~/_ipython/collect dir (in win32 at least). | |||
""" | |||
vivainio
|
r964 | from IPython.external.path import path | |
Brian Granger
|
r2322 | basedir = path(ip.ipython_dir + '/collect') | |
vivainio
|
r851 | try: | |
fs = mglob.expand(arg.split(None,1)[1]) | |||
except IndexError: | |||
os.startfile(basedir) | |||
return | |||
for f in fs: | |||
f = path(f) | |||
trg = basedir / f.splitdrive()[1].lstrip('/\\') | |||
if f.isdir(): | |||
print "mkdir",trg | |||
trg.makedirs() | |||
continue | |||
dname = trg.dirname() | |||
if not dname.isdir(): | |||
dname.makedirs() | |||
print f,"=>",trg | |||
shutil.copy2(f,trg) | |||
Brian Granger
|
r2205 | ip.define_alias("collect",collect) | |
vivainio
|
r851 | ||
def inote(ip,arg): | |||
""" inote Hello world | |||
Adds timestamp and Hello world to ~/_ipython/notes.txt | |||
Without args, opens notes.txt for editing. | |||
""" | |||
import time | |||
Brian Granger
|
r2322 | fname = ip.ipython_dir + '/notes.txt' | |
vivainio
|
r851 | ||
try: | |||
entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' | |||
f= open(fname, 'a').write(entry) | |||
except IndexError: | |||
Brian Granger
|
r2205 | ip.hooks.editor(fname) | |
vivainio
|
r851 | ||
Brian Granger
|
r2205 | ip.define_alias("inote",inote) | |
vivainio
|
r912 | ||
def pathobj_mangle(p): | |||
return p.replace(' ', '__').replace('.','DOT') | |||
def pathobj_unmangle(s): | |||
return s.replace('__',' ').replace('DOT','.') | |||
vivainio
|
r915 | class PathObj(path): | |
vivainio
|
r912 | def __init__(self,p): | |
self.path = p | |||
vivainio
|
r914 | if p != '.': | |
self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)] | |||
else: | |||
vivainio
|
r912 | self.ents = None | |
def __complete__(self): | |||
vivainio
|
r914 | if self.path != '.': | |
vivainio
|
r912 | return self.ents | |
vivainio
|
r914 | self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')] | |
return self.ents | |||
vivainio
|
r912 | def __getattr__(self,name): | |
if name in self.ents: | |||
if self.path.endswith('/'): | |||
sep = '' | |||
else: | |||
sep = '/' | |||
tgt = self.path + sep + pathobj_unmangle(name) | |||
#print "tgt",tgt | |||
if os.path.isdir(tgt): | |||
return PathObj(tgt) | |||
if os.path.isfile(tgt): | |||
vivainio
|
r914 | return path(tgt) | |
vivainio
|
r912 | ||
raise AttributeError, name # <<< DON'T FORGET THIS LINE !! | |||
def __str__(self): | |||
return self.path | |||
def __repr__(self): | |||
return "<PathObj to %s>" % self.path | |||
def __call__(self): | |||
print "cd:",self.path | |||
os.chdir(self.path) | |||
vivainio
|
r915 | def complete_pathobj(obj, prev_completions): | |
vivainio
|
r912 | if hasattr(obj,'__complete__'): | |
vivainio
|
r915 | res = obj.__complete__() | |
if res: | |||
return res | |||
# just return normal attributes of 'path' object if the dir is empty | |||
Brian Granger
|
r2205 | raise TryNext | |
vivainio
|
r912 | ||
Brian Granger
|
r2022 | complete_pathobj = IPython.utils.generics.complete_object.when_type(PathObj)(complete_pathobj) | |
vivainio
|
r912 | ||
def test_pathobj(): | |||
#p = PathObj('c:/prj') | |||
#p2 = p.cgi | |||
#print p,p2 | |||
vivainio
|
r915 | rootdir = PathObj("/") | |
vivainio
|
r912 | startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs") | |
vivainio
|
r914 | cwd = PathObj('.') | |
Brian Granger
|
r2205 | ip.push("rootdir startmenu cwd") | |
vivainio
|
r912 | ||
#test_pathobj() |