A different way to do I/O redirection
sometimes i encounter situations where i am putting a command in where i cannot use I/O redirection.
when i am providing a command as token words to a program or other command, using redirection may not work or be understood. the command may be read by the program or be provided in arguments on the command line that runs the program. for example it could be running the provided command somewhere else like a different directory, different user, or different host. maybe the redirection needs to be done remotely. if you can run a one-time command string in that shell, such as the -c option for /bin/sh you might be able to quote the entire command.
not all situations can do that. perhaps quoting cannot be used. perhaps the command will get parsed and apply the redirection in the wrong place.
i have created a workaround for this. a single shell script that changes its behavior based on the command name used to run it. it has 3 primary commands it can do, "i", "o", and "e". used with a single letter name, it takes on file name followed by one command. it will redirect one standard I/O descriptor according to which letter is used then run the given command. for example:
if you want to do more than one redirection, you could cascade the commands:
the script can handle 2 or 3 letters in its name to handle multiple redirection. the file names are used in the order of the letters:
it's one script in Python3. you can make symlinks for all the other names you want to use. here is the script:
eio.py:
when i am providing a command as token words to a program or other command, using redirection may not work or be understood. the command may be read by the program or be provided in arguments on the command line that runs the program. for example it could be running the provided command somewhere else like a different directory, different user, or different host. maybe the redirection needs to be done remotely. if you can run a one-time command string in that shell, such as the -c option for /bin/sh you might be able to quote the entire command.
not all situations can do that. perhaps quoting cannot be used. perhaps the command will get parsed and apply the redirection in the wrong place.
i have created a workaround for this. a single shell script that changes its behavior based on the command name used to run it. it has 3 primary commands it can do, "i", "o", and "e". used with a single letter name, it takes on file name followed by one command. it will redirect one standard I/O descriptor according to which letter is used then run the given command. for example:
Code:
i inputfile command its arguments o outputfile othercommand its arguments e erroroutputfile somecommand its arguments
Code:
i inputfile o outputfile e erroroutputfile command its arguments
Code:
oi outputfile inputfile command its arguments ioe inputfile outputfile erroroutputfile command its arguments
eio.py:
Code:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """eio (or its custom aliases): Copyright © 2021, by Phil D. Howard - all other rights reserved Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. The author may be contacted by decoding the number 11054987560151472272755686915985840251291393453694611309 (provu igi la numeron al duuma) with command name, 1-3 file names, then command to run and its args, it redirects 1-3 files to stdin/stdout/stderr of the command to run. the order of the letters is the order of the file name arguments. any alias can be used that has 1-3 of these letters: eio letters eioa in command name imply files or mode: e - open next named file to write stderr i - open next named file to read stdin o - open next named file to write stdout a - use append mode for stdout and/or stderr invalid alias names may have goofy results or worse. the same letter more than once is ambiguous/invalid. you can omit the command to run and it runs /bin/cat. intended for POSIX systems (uses file descriptors). tested on Ubuntu Linux. """ from sys import argv as v import os fds = dict( # map eio letter to fd i = 0, o = 1, e = 2, ) flags = ( # map fd to flags os.O_RDONLY, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, ) cmd = v.pop(0).rsplit('/',1)[-1].rsplit('.',1)[0].lower() fns = [None]*3 s = set() for l in cmd: if l in s: exit(f'letter {l!r} repeats in command name') if l=='a': flags[1] |= os.O_APPEND flags[2] |= os.O_APPEND if l in fds: if not v: exit(f'file name missing for {l!r}') fns[fds[l]] = v.pop(0) s.add(l) if not v: v = ['/bin/cat'] n = len(s) if n>1 and not v: exit(f'command missing after {n} file names') er = 0 for fd in (0,1,2): fn = fns[fd] if fn: if not fn: continue if fn=='-': continue try: nd = os.open(fn,flags[fd]) except Exception: nd = -9 if nd<0: print(f'error {nd} opening file {fn!r}, command {v[0]!r} not run') er += 1 else: os.dup2(nd,fd) if er: exit(f'aborting due to {er} error{"s"[er==1:]}') if not v: v = ['/bin/cat'] os.execvp(v[0],v)
Total Comments 0