top of page
  • Writer's pictureJack Orenstein

Marcel the Shell

Welcome to marcel! Marcel is yet another shell that pipes objects between commands, instead of strings. What is different about marcel is it's reliance on Python. First, it is implemented in Python.

Second, marcel exposes Python. If you have an input stream of Files and you want to output a stream of (file name, file size) tuples, then you can use the map operator, which applies a function to input values to generate output values. The function used by the map operator is an ordinary Python function. So for example:

ls -fr | map (lambda file: (file.path, file.size))

ls -fr visits the current directly recursively (-r) and outputs files only (-f), not directories or symlinks. The function is in parentheses, (you could omit the lambda keyword if you'd like).

Third, marcel uses Python to take a different approach to scripting. Shell commands are augmented by control structures and rudimentary datatypes to provide a scripting language. These languages are usually pretty poorly designed, (e.g. bash). And of course, it's yet another language to learn. Furthermore, individual commands have extensive sub-languages, and to do anything sophisticated requires the reading of man pages documenting these sub-languages.

The marcel approach is to recognize that Python is a good programming language, but is bad at scripting because of the API to the host OS. You can't just run the ls command from Python, for example, you have to use something like subprocess.Popen. Piping requires chaining the stdin/stdout arguments together from successive Popen calls. Marcel offers an API module, marcel.api, which provides much cleaner integration. For example, the above example, done as Python code:

from marcel.api import *

for path, size in (ls(file=True, recursive=True) 
                   | map(lambda file: (file.path, file.size))):
    print(f'{file.path}: {file.size})

The ls -fr command, which was used in the shell, turns into ls(file=True, recursive=True) in the API. The pipe symbol again pipes the ls output to the map input. The command output is made available as a Python iterator, so that a for loop can iterate over the results.

134 views5 comments

Recent Posts

See All

Marcel in more places

Thanks to two different pilot errors on my part, I have broken the packaging system of two OSes that package marcel. I would have had no idea they were including marcel otherwise. In any case, I'm hap

Marcel and Jupyter

For years, I kept hearing about iPython, as a vastly improved Python REPL. I played with it a little bit, and yes, I saw that. I found that Object Shell (a forerunner of marcel) ran in iPython with no

8 Queens as a Marcel One-Liner

Yes, the 8 Queens problem can be solved in marcel, as a one-liner even. If you want the details, you can find them here. But the basic idea is this: Use Python's itertools.permutations to generate can

bottom of page