I'm trying to figure out how to run this command using subprocess.run()
:
cmd = 'find / \( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune \) -o ! -type l -type f -or -type d -printf "depth="%d/"perm="%m/"size="%s/"atime="%A@/"mtime"=%T@/"ctime"=%C@/"hardlinks"=%n/"selinux_context"=%Z/"user="%u/"group="%g/"name="%p/"type="%Y\\n'
I've put the command into a list, even removing items, etc:
cmd = [
'find',
'/',
'\( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune \)',
'-o',
'! -type l',
'-type f',
'-or',
'-type d'
]
I've tried running the command using /bin/bash
:
cmd = '/bin/bash -c find / \( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune \) -o ! -type l -type f -or -type d -printf "depth="%d/"perm="%m/"size="%s/"atime="%A@/"mtime"=%T@/"ctime"=%C@/"hardlinks"=%n/"selinux_context"=%Z/"user="%u/"group="%g/"name="%p/"type="%Y\\n'
Doesn't matter. Everything I've tried does not work. Either I get no output at all, or it lists the files in my home directory, or I get an error, e.g.: b'find: paths must precede expression: ! -type l\nUsage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]\n'
Is there any easy way to take a command that works at the command line and just parse the string into whatever list elements subprocess.run()
wants?
CodePudding user response:
Parsing With shlex.parse()
After fixing the incorrect quotes in your printf string, we get:
cmd = r'''
find / \( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune \) -o ! -type l -type f -or -type d -printf 'depth=%d/perm=%m/size=%s/atime=%A@/mtime=%T@/ctime=%C@/hardlinks=%n/selinux_context=%Z/user=%u/group=%g/name=%p/type=%Y\\n'
'''
print(shlex.split(cmd))
...which emits an entirely correct result, and subprocess.call()
works with it properly.
Building A Correct Command Line By Hand
In terms of what it looks like to do this by hand:
cmd = [
'find', '/',
'(',
'-path', '/mnt', '-prune',
'-o', '-path', '/dev', '-prune',
'-o', '-path', '/proc', '-prune',
'-o', '-path', '/sys', '-prune',
')',
'-o', '!', '-type', 'l',
'-type', 'f',
'-or',
'-type', 'd',
'-printf', 'depth=%d/perm=%m/size=%s/atime=%A@/mtime=%T@/ctime=%C@/hardlinks=%n/selinux_context=%Z/user=%u/group=%g/name=%p/type=%Y\n'
]
Note:
- Syntactic quotes change the shell's parsing mode, they don't become part of the data.
"foo"
just becomesfoo
;"foo"bar"baz"
becomesfoobarbaz
. So you can't/shouldn't/don't try to put those quotes into the data that Python is passing in. - This is true also for
\(
: the backslash is shell syntax. It doesn't actually become one offind
's arguments, so you leave it out. - Any space that isn't quoted or escaped separates words; so
-type f
in shell is'-type', 'f'
, two separate words.