小伙伴们,大家好。
今天所面对的场景是,我需要通过java来执行linux和windows的复制文件的命令,但是我的文件名中存在了空格,所以就导致了报错。
我的命令是这样的
cp -r /Users/joshua/Documents/wordSpace/G1/target/g1/clientBackupVersion/upload_file/g1_joshua/storage/g1_config.sv_c_custom_html/files/一粒麦子" "和弦简谱.zip /Users/joshua/Documents/g1_upload/g1_joshua/storage/g1_config.sv_c_custom_html/files/一粒麦子" "和弦简谱.zip
但是我当我通过runtime 执行的时候,给我报了这样的一个错误
ERROR>cp: "和弦简谱.zip is not a directory
于是乎,我跟了一下源码,为什么会变成这样,情况是这样的。
着急的小伙伴可以直接跳到标题二去看解决方案,不过我个人还是建议咱们知道下具体实现能更得心应手一点,下次就不至于忘记怎么解决啦。
一、问题原因调查
首先,我们来到入口
在这里,我们点下去,发现他调用了另一个exec方法
然后,我们继续往下跟,跟到了有逻辑的一层exec方法
其实我们的命令在这一步就被分割啦,我们走到450行
然后查看447行的cmdarray,发现我们的命令被分割了
接下来,我们来看,他是按着什么规则来进行的分割,我们点446行的new StringTokenizer(command); 就会发现,他是按着下面的五个字符来分割的。
['','\t','\n','\r','\f']
所以,我们如果想让他不被分割,就跳过这一步,那么就直接执行Runtime.java的第450行
在这里,我们需要知道,他这三个参数的意思,所以我们再往里点一层
我们根据上面的英文注释翻译就可以得知这三个参数的意思了
cmdarray–包含要调用的命令及其参数的数组。
envp–字符串数组,其中每个元素的环境变量设置格式为name=value,如果子流程应该继承当前流程的环境,则为null。
dir–子流程的工作目录,如果子流程应该继承当前流程的工作路径,则为null。
看到这里,我们就发现,我们其实只需要第一个参数,那么我反向跟代码,就是来看这个方法哪里调用过
,我们发现,他有一个方法是只传了第一个参数的,我们点过去看一下
我们看到了这里,就知道,这个就是我们想要的方法啦。那么我们接下来就开始动手写这样的一个方法来满足我们的需求。
---------------------------------------------------我是分割线------------------------------------------------
二、解决方案
接下来,我们来写一个方法调用这个api
在这里,我们来看我们要如何去传这个字符串数组
由于我们要执行的是linux的命令
所以我们这样传值
execOSCommons(new String[]{"/bin/sh","-c",command});
在这几个参数里,"/bin/sh"和"-c"是固定的,command就是我们的命令。
最后,我们就会发现,这个文件已经成功的被复制过去啦。
如果有什么疑问,或者指教 欢迎加QQ:1318623133
----------------------------------------- I`am Joshua,may god bless you