How to emulate backtick subshells in plumbum

82 Views Asked by At

I want to write this command in Plumbum:

foo `date +%H%M%S`

or, equivalently:

foo $(date +%H%M%S)

(think of 'foo' as a command like 'mkdir')

How can I write this in Plumbum? I want to have this as a Plumbum object that I can reuse - ie each time I call it I call 'foo' with the current time, being different each call.

I tried using a subshell. This example:

#!/usr/bin/env python3
from plumbum import local
import time
s = local["sh"]
f = s["-c", "mkdir", "$(date +%H%M%S)"]
for i in range(0,10):
  f()
  time.sleep(1)

doesn't work because I get:

plumbum.commands.processes.ProcessExecutionError: Unexpected exit code: 1
Command line: | /usr/bin/sh -c mkdir '$(date +%H%M%S)'
Stderr:       | mkdir: missing operand
              | Try 'mkdir --help' for more information.

I could use time.localtime() to compute the time in Python, but that would be the same for every evaluation. I could also generate a shell script file with this in, but then I'd have to clean that up afterwards.

How can I write this in a Plumbum-native way?

2

There are 2 best solutions below

1
On BEST ANSWER

You came close to having something that would work with sh -c. The trick is to understand that only the one argument directly after the -c is parsed as code by the shell; subsequent arguments go into $0, $1, etc. in the context in which that code is executed.

s = local['sh']
f = s['-c', 'mkdir "$(date +%H%M%S)"']

That said, I'd strongly argue that plumbum is being more of a hinderance than a help, and suggest getting rid of it outright.

0
On

I haven't found a way to do it using Plumbum API, but introducing a wrapper function works:

import time
from plumbum.cmd import mkdir, date


def mkdate():
    return mkdir[date['+%H%M%S']()]


for i in range(0, 3):
    mkdate()
    time.sleep(1)

mkdate is a regular function, unfortunately, not a Plumbum object, but I haven't found anything in the docs right away =)