|
|
@ -9,6 +9,7 @@ import os
|
|
|
|
import shutil
|
|
|
|
import shutil
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
from typing import List, Union, Tuple, Any, Optional, Dict, cast
|
|
|
|
from typing import List, Union, Tuple, Any, Optional, Dict, cast
|
|
|
|
|
|
|
|
import fnmatch
|
|
|
|
import anytree # type: ignore
|
|
|
|
import anytree # type: ignore
|
|
|
|
from natsort import os_sort_keygen # type: ignore
|
|
|
|
from natsort import os_sort_keygen # type: ignore
|
|
|
|
|
|
|
|
|
|
|
@ -17,7 +18,8 @@ from catcli import nodes
|
|
|
|
from catcli.nodes import NodeAny, NodeStorage, \
|
|
|
|
from catcli.nodes import NodeAny, NodeStorage, \
|
|
|
|
NodeTop, NodeFile, NodeArchived, NodeDir, NodeMeta, \
|
|
|
|
NodeTop, NodeFile, NodeArchived, NodeDir, NodeMeta, \
|
|
|
|
typcast_node
|
|
|
|
typcast_node
|
|
|
|
from catcli.utils import md5sum, fix_badchars, has_attr
|
|
|
|
from catcli.utils import md5sum, fix_badchars, has_attr, \
|
|
|
|
|
|
|
|
get_node_fullpath
|
|
|
|
from catcli.logger import Logger
|
|
|
|
from catcli.logger import Logger
|
|
|
|
from catcli.printer_native import NativePrinter
|
|
|
|
from catcli.printer_native import NativePrinter
|
|
|
|
from catcli.printer_csv import CsvPrinter
|
|
|
|
from catcli.printer_csv import CsvPrinter
|
|
|
@ -35,8 +37,7 @@ class Noder:
|
|
|
|
* "dir" node representing a directory
|
|
|
|
* "dir" node representing a directory
|
|
|
|
* "file" node representing a file
|
|
|
|
* "file" node representing a file
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
# pylint: disable=R0904
|
|
|
|
PRE = ' '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, debug: bool = False,
|
|
|
|
def __init__(self, debug: bool = False,
|
|
|
|
sortsize: bool = False,
|
|
|
|
sortsize: bool = False,
|
|
|
@ -292,11 +293,11 @@ class Noder:
|
|
|
|
@sep: CSV separator character
|
|
|
|
@sep: CSV separator character
|
|
|
|
@raw: print raw size rather than human readable
|
|
|
|
@raw: print raw size rather than human readable
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
typcast_node(node)
|
|
|
|
if not node:
|
|
|
|
if not node:
|
|
|
|
return
|
|
|
|
return
|
|
|
|
if node.type == nodes.TYPE_TOP:
|
|
|
|
if node.type == nodes.TYPE_TOP:
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if node.type == nodes.TYPE_STORAGE:
|
|
|
|
if node.type == nodes.TYPE_STORAGE:
|
|
|
|
self.csv_printer.print_storage(node,
|
|
|
|
self.csv_printer.print_storage(node,
|
|
|
|
sep=sep,
|
|
|
|
sep=sep,
|
|
|
@ -341,20 +342,18 @@ class Noder:
|
|
|
|
@withstorage: print the node storage it belongs to
|
|
|
|
@withstorage: print the node storage it belongs to
|
|
|
|
@raw: print raw size rather than human readable
|
|
|
|
@raw: print raw size rather than human readable
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
typcast_node(node)
|
|
|
|
if node.type == nodes.TYPE_TOP:
|
|
|
|
if node.type == nodes.TYPE_TOP:
|
|
|
|
# top node
|
|
|
|
# top node
|
|
|
|
node.__class__ = NodeTop
|
|
|
|
|
|
|
|
self.native_printer.print_top(pre, node.name)
|
|
|
|
self.native_printer.print_top(pre, node.name)
|
|
|
|
elif node.type == nodes.TYPE_FILE:
|
|
|
|
elif node.type == nodes.TYPE_FILE:
|
|
|
|
# node of type file
|
|
|
|
# node of type file
|
|
|
|
node.__class__ = NodeFile
|
|
|
|
|
|
|
|
self.native_printer.print_file(pre, node,
|
|
|
|
self.native_printer.print_file(pre, node,
|
|
|
|
withpath=withpath,
|
|
|
|
withpath=withpath,
|
|
|
|
withstorage=withstorage,
|
|
|
|
withstorage=withstorage,
|
|
|
|
raw=raw)
|
|
|
|
raw=raw)
|
|
|
|
elif node.type == nodes.TYPE_DIR:
|
|
|
|
elif node.type == nodes.TYPE_DIR:
|
|
|
|
# node of type directory
|
|
|
|
# node of type directory
|
|
|
|
node.__class__ = NodeDir
|
|
|
|
|
|
|
|
self.native_printer.print_dir(pre,
|
|
|
|
self.native_printer.print_dir(pre,
|
|
|
|
node,
|
|
|
|
node,
|
|
|
|
withpath=withpath,
|
|
|
|
withpath=withpath,
|
|
|
@ -363,14 +362,11 @@ class Noder:
|
|
|
|
raw=raw)
|
|
|
|
raw=raw)
|
|
|
|
elif node.type == nodes.TYPE_STORAGE:
|
|
|
|
elif node.type == nodes.TYPE_STORAGE:
|
|
|
|
# node of type storage
|
|
|
|
# node of type storage
|
|
|
|
node.__class__ = NodeStorage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.native_printer.print_storage(pre,
|
|
|
|
self.native_printer.print_storage(pre,
|
|
|
|
node,
|
|
|
|
node,
|
|
|
|
raw=raw)
|
|
|
|
raw=raw)
|
|
|
|
elif node.type == nodes.TYPE_ARCHIVED:
|
|
|
|
elif node.type == nodes.TYPE_ARCHIVED:
|
|
|
|
# archive node
|
|
|
|
# archive node
|
|
|
|
node.__class__ = NodeArchived
|
|
|
|
|
|
|
|
if self.arc:
|
|
|
|
if self.arc:
|
|
|
|
self.native_printer.print_archive(pre, node.name, node.archive)
|
|
|
|
self.native_printer.print_archive(pre, node.name, node.archive)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@ -458,7 +454,7 @@ class Noder:
|
|
|
|
###############################################################
|
|
|
|
###############################################################
|
|
|
|
# searching
|
|
|
|
# searching
|
|
|
|
###############################################################
|
|
|
|
###############################################################
|
|
|
|
def find_name(self, top: NodeTop,
|
|
|
|
def find(self, top: NodeTop,
|
|
|
|
key: str,
|
|
|
|
key: str,
|
|
|
|
script: bool = False,
|
|
|
|
script: bool = False,
|
|
|
|
only_dir: bool = False,
|
|
|
|
only_dir: bool = False,
|
|
|
@ -511,7 +507,8 @@ class Noder:
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
if fmt == 'native':
|
|
|
|
if fmt == 'native':
|
|
|
|
for _, item in paths.items():
|
|
|
|
for _, item in paths.items():
|
|
|
|
self._print_node_native(item, withpath=True,
|
|
|
|
self._print_node_native(item,
|
|
|
|
|
|
|
|
withpath=True,
|
|
|
|
withnbchildren=True,
|
|
|
|
withnbchildren=True,
|
|
|
|
withstorage=True,
|
|
|
|
withstorage=True,
|
|
|
|
raw=raw)
|
|
|
|
raw=raw)
|
|
|
@ -533,6 +530,7 @@ class Noder:
|
|
|
|
def _callback_find_name(self, term: str, only_dir: bool) -> Any:
|
|
|
|
def _callback_find_name(self, term: str, only_dir: bool) -> Any:
|
|
|
|
"""callback for finding files"""
|
|
|
|
"""callback for finding files"""
|
|
|
|
def find_name(node: NodeAny) -> bool:
|
|
|
|
def find_name(node: NodeAny) -> bool:
|
|
|
|
|
|
|
|
path = get_node_fullpath(node)
|
|
|
|
if node.type == nodes.TYPE_STORAGE:
|
|
|
|
if node.type == nodes.TYPE_STORAGE:
|
|
|
|
# ignore storage nodes
|
|
|
|
# ignore storage nodes
|
|
|
|
return False
|
|
|
|
return False
|
|
|
@ -549,7 +547,9 @@ class Noder:
|
|
|
|
# filter
|
|
|
|
# filter
|
|
|
|
if not term:
|
|
|
|
if not term:
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
if term.lower() in node.name.lower():
|
|
|
|
if term in path:
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
if fnmatch.fnmatch(path, term):
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
# ignore
|
|
|
|
# ignore
|
|
|
@ -572,17 +572,18 @@ class Noder:
|
|
|
|
@fmt: output format
|
|
|
|
@fmt: output format
|
|
|
|
@raw: print raw size
|
|
|
|
@raw: print raw size
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
self._debug(f'walking path: \"{path}\" from {top.name}')
|
|
|
|
self._debug(f'walking path: \"{path}\" from \"{top.name}\"')
|
|
|
|
|
|
|
|
|
|
|
|
resolv = anytree.resolver.Resolver('name')
|
|
|
|
resolv = anytree.resolver.Resolver('name')
|
|
|
|
found = []
|
|
|
|
found = []
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
if '*' in path or '?' in path:
|
|
|
|
if '*' in path or '?' in path:
|
|
|
|
# we need to handle glob
|
|
|
|
# we need to handle glob
|
|
|
|
self._debug(f'glob with top {top.name} and path {path}')
|
|
|
|
self._debug('glob ls...')
|
|
|
|
found = resolv.glob(top, path)
|
|
|
|
found = resolv.glob(top, path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# we have a canonical path
|
|
|
|
# we have a canonical path
|
|
|
|
|
|
|
|
self._debug('get ls...')
|
|
|
|
found = resolv.get(top, path)
|
|
|
|
found = resolv.get(top, path)
|
|
|
|
if found and self.node_has_subs(found):
|
|
|
|
if found and self.node_has_subs(found):
|
|
|
|
# let's find its children as well
|
|
|
|
# let's find its children as well
|
|
|
@ -604,24 +605,12 @@ class Noder:
|
|
|
|
# sort found nodes
|
|
|
|
# sort found nodes
|
|
|
|
found = sorted(found, key=os_sort_keygen(self._sort))
|
|
|
|
found = sorted(found, key=os_sort_keygen(self._sort))
|
|
|
|
|
|
|
|
|
|
|
|
# print the parent
|
|
|
|
|
|
|
|
if fmt == 'native':
|
|
|
|
|
|
|
|
self._print_node_native(found[0].parent,
|
|
|
|
|
|
|
|
withpath=False,
|
|
|
|
|
|
|
|
withnbchildren=True,
|
|
|
|
|
|
|
|
raw=raw)
|
|
|
|
|
|
|
|
elif fmt.startswith('csv'):
|
|
|
|
|
|
|
|
self._print_node_csv(found[0].parent, raw=raw)
|
|
|
|
|
|
|
|
elif fmt.startswith('fzf'):
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# print all found nodes
|
|
|
|
# print all found nodes
|
|
|
|
if fmt == 'csv-with-header':
|
|
|
|
if fmt == 'csv-with-header':
|
|
|
|
self.csv_printer.print_header()
|
|
|
|
self.csv_printer.print_header()
|
|
|
|
for item in found:
|
|
|
|
for item in found:
|
|
|
|
if fmt == 'native':
|
|
|
|
if fmt == 'native':
|
|
|
|
self._print_node_native(item, withpath=False,
|
|
|
|
self._print_node_native(item, withpath=False,
|
|
|
|
pre=Noder.PRE,
|
|
|
|
|
|
|
|
withnbchildren=True,
|
|
|
|
withnbchildren=True,
|
|
|
|
raw=raw)
|
|
|
|
raw=raw)
|
|
|
|
elif fmt.startswith('csv'):
|
|
|
|
elif fmt.startswith('csv'):
|
|
|
|