首页 > 解决方案 > bash命令未通过python运行

问题描述

我有以下方法:

def _run_command(bash_command: str) -> str:
    """
    Run a bash command.

    Args:
        bash_command: command to be executed.
    """
    logging.info(f"Running {bash_command}.")
    process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
    output, error = process.communicate()
    if error is not None:
        logging.exception(f"Error running command: {bash_command}")
        raise ValueError(error)

    return str(output)

我用来通过 Python 运行 shell 命令。它似乎适用于大多数情况,除了这个:

command = f'find {self._prefix} -name "*.txt" -type f -delete'
output = self._run_command(command)

self._prefix诸如 的路径在哪里/opt/annotations/?我希望这个命令会删除该路径内的所有 txt 文件,但这种情况不会发生。但是,如果我find /opt/annotations/ -name "*.txt" -type f -delete直接在终端中运行此命令,所有内容都会按预期删除。所以我想知道我是否在这里遗漏了什么。

日志显示了 expect 命令,但是,txt 没有被删除:

2020-11-18 19:07:47 fm-101 root[10] INFO Running find /opt/annotations/ -name "*.txt" -type f -delete.

标签: pythonshellsubprocess

解决方案


问题是引号。您没有匹配的文件"*.txt",但只有匹配的文件*.txt

将您的命令显式作为列表传递,而不是尝试从字符串生成列表,以避免此问题和其他问题:

def _run_command(command_argv: list) -> str:
    logging.info(f"Running {command_argv}.")
    process = subprocess.Popen(command_argv, stdout=subprocess.PIPE)
    output, error = process.communicate()
    if error is not None:
        logging.exception(f"Error running command: {bash_command}")
        raise ValueError(error)
    return str(output)

_run_command(['find', str(self._prefix), '-name', '*.txt', '-type', 'f', '-delete'])

如果您坚持将参数作为字符串,请使用shlex.split()POSIX sh-like (不是 bash-like) 处理引用值:

def _run_command(shell_command: str) -> str:
    """
    Run a shell command, but without actually invoking any shell

    Args:
        shell_command: command to be executed.
    """
    logging.info(f"Running {shell_command}.")
    process = subprocess.Popen(shlex.split(shell_command), stdout=subprocess.PIPE)
    output, error = process.communicate()
    if error is not None:
        logging.exception(f"Error running command: {shell_command}")
        raise ValueError(error)

    return str(output)

...但这只能解决报价删除的具体问题;它不会使操作在任何其他方面与 shell 兼容。


推荐阅读