python 子进程远程查找 -exec 文件名 space

python subprocess remote find -exec filename with space

所以我有一个远程 Linux 服务器,我想 运行 我本地机器上的一个 Python 脚本列出特定文件夹中的所有文件及其修改日期远程服务器。到目前为止,这是我的代码:

command = "find \""+to_directory+'''\"* -type f -exec sh -c \"stat -c \'%y:%n\' \'{}\'\" \;'''

scp_process_ = subprocess.run("ssh "+to_user+"@"+to_host+" '"+command+"' ", shell=True, capture_output=False, text=True)

现在运行执行命令

find "/shares/Public/Datensicherung/"* -type f -exec sh -c "stat -c '%y:%n' '{}'" \;

在服务器本身上工作正常,没有任何错误。

但是,一旦我使用子进程通过 ssh 远程 运行 它,文件夹中的文件就会出现问题 spaces: "/shares/Public/Datensicherung/New [=26= .txt" 里面有 space:

stat: can't stat '/shares/Public/Datensicherung/New': No such file or directory
stat: can't stat 'folder/hi.txt': No such file or directory 

我知道它搞砸了,但这是我可以构建的最佳解决方案。 我想坚持使用 subprocess 和 ssh,但如果您有更好的解决方案,请随时 post 它。

有时问题的发生是因为命令字符串格式错误。出于与 Unix 通信的目的,shell 被创建 shlex module. So basically you wrap your code with shlex,然后将其传递给 supbrocess.run

我没有看到要调用的实际最终命令,但您可以自己使用 shlex.split 将其拆分为正确的命令。

根据你的例子,它会是这样的:

from shlex import join

cmd = join(['ssh',
 f'{to_user}@{to_host}',
 'find',
 f'{to_directory}*',
 '-type',
 'f',
 '-exec',
 'sh',
 '-c',
 "stat -c '%y:%n' '{}'",
 ';']))

scp_process_ = subprocess.run(cmd, shell=True, capture_output=False, text=True)

此外,您可能想尝试一下 shell=True 选项。

使用 shell=True 您将调用 三个 shell 个实例,每个实例都需要一层引用。当然,这是可能的,但如果可能的话,有很多理由要避免它。

首先,您可以轻松避免本地 shell=True,这实际上提高了 Python 代码的稳健性和清晰度。

command = "find \""+to_directory+'''\"* -type f -exec sh -c \"stat -c \'%y:%n\' \'{}\'\" \;'''

scp_process_ = subprocess.run(
    ["ssh", to_user+"@"+to_host, command],
    capture_output=False, text=True)

其次,stat可以很容易地接受多个参数,所以你也可以去掉sh -c '...'

command = 'find "' + to_directory + '" -type f -exec stat -c "%y:%n" {} +'

优化还会将 + 切换为 \;(因此 sh -c '' 包装器无论如何都是无用的)。