如何将含空格文件名的git ls-files输出正确传入Java程序?
问题分析与解决办法
你的问题核心在于Shell对命令替换和引号的处理顺序,我们一步步拆解:
为什么加引号的sed方案没用?
当你执行java Test $(git ls-files | sed "s/\(.*\)/'\1'/g")时,Shell的执行流程是:
- 先运行
git ls-files | sed ...,得到的输出是'input $.csv' 'input_1.csv' 'input_2.csv' 'input_3.csv' - Shell对这个输出进行单词拆分(默认按空格、制表符、换行分割),这时候单引号只是输出中的普通字符,不是Shell的语法引号。所以最终传给Java的参数是:
'input$.csv''input_1.csv'- ...
也就是说,带空格的文件名依然被拆成了两个参数,还多了多余的单引号。
正确的解决方法
方法1:用xargs传递参数(最简单)
git ls-files默认会把每个文件名输出在单独一行,xargs可以识别换行作为分隔符,正确将每个文件名作为独立参数传递:
git ls-files | xargs java Test
方法2:用Bash数组保存文件名(更可控)
如果需要在传递前对文件名做处理,可以用数组存储每个文件名,再展开传递:
# 用readarray读取git输出到数组,-t选项去掉每行末尾的换行符 readarray -t file_list < <(git ls-files) # 展开数组时用双引号包裹,确保每个元素作为独立参数 java Test "${file_list[@]}"
方法3:处理包含特殊字符的文件名(最安全)
如果文件名里不仅有空格,还有换行、制表符等特殊字符,推荐用git ls-files -z输出以null字符分隔的文件名,再配合xargs -0处理:
git ls-files -z | xargs -0 java Test
null字符是唯一不会出现在文件名里的字符,这种方式能处理所有合法的文件名。
总结
Shell的命令替换$(...)展开后,会优先进行单词拆分,输出中的引号只是普通文本,无法阻止拆分。要正确传递带空格的文件名,需要让Shell把每个文件名当作一个整体,以上三种方法都能实现这个目标。
内容的提问来源于stack exchange,提问作者Jun
相关产品推荐
相关产品推荐

