简体   繁体   English

python 子进程远程查找 -exec 带空格的文件名

[英]python subprocess remote find -exec filename with space

So I have a remote Linux Server and would like to run a Python Script on my local machine to list all files and their modification dates in a specific folder on that remote server.因此,我有一个远程 Linux 服务器,并想在我的本地计算机上运行 Python 脚本,以列出该远程服务器上特定文件夹中的所有文件及其修改日期。 That is my code so far:到目前为止,这是我的代码:

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)

Now running the command现在运行命令

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

on the server itself works fine without any error.服务器本身工作正常,没有任何错误。

But as soon I use a subprocess to run it remotely over ssh it has a problem with a file in a folder with spaces: "/shares/Public/Datensicherung/New folder/hi.txt" with a space in it:但是,一旦我使用子进程通过 ssh 远程运行它,它就会出现一个带有空格的文件夹中的文件问题:“/shares/Public/Datensicherung/New folder/hi.txt”,其中有一个空格:

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 

I know it is messed up, but that is the best solution I could build.我知道它搞砸了,但这是我可以构建的最佳解决方案。 I would like to stick with subprocess and ssh but if you have a better solution feel free to post it.我想坚持使用 subprocess 和 ssh 但如果您有更好的解决方案,请随时发布。

With shell=True you are invoking three shell instances, each of which requires a layer of quoting.使用shell=True您正在调用三个shell 实例,每个实例都需要一层引用。 This is possible to do, of course, but there are many reasons to avoid it if at all possible.当然,这是可以做到的,但如果可能的话,有很多理由要避免它。

First off, you can easily avoid the local shell=True and this actually improves the robustness and clarity of your Python code.首先,您可以轻松避免本地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)

Secondly, stat can easily accept multiple arguments, so you can take out the sh -c '...' too.其次, stat可以很方便的接受多个arguments,所以也可以去掉sh -c '...'

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

The optimization also switches + for \;优化还切换+\; (so the sh -c '' wrapper was doubly useless anyway). (所以sh -c ''包装器无论如何都是双重无用的)。

Sometimes the issue happening because malformed command string.有时会因为格式错误的命令字符串而发生问题。 For purpose of comunication with Unix shell was craeted shlex module.为了与 Unix shell 通信,创建了shlex模块。 So basically you wrap your code with shlex and then pass it into supbrocess.run .所以基本上你用shlex包装你的代码,然后将它传递给supbrocess.run

I don't see the actual final cmd to call but you could split it to proper command with shlex.split by yourself.我没有看到要调用的实际最终 cmd ,但您可以自己使用shlex.split将其拆分为正确的命令。

From your example it would be something like:从您的示例中,它将类似于:

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)

Also, you maybe want to play around with shell=True option.此外,您可能想玩一下shell=True选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM