在这种情况下,为什么论点定界在bash中失败?

时间:2018-07-07 19:14:35

标签: ruby bash parsing argv command-substitution

我有一个用Ruby(mp3join)编写的实用程序,该实用程序带有“ n”个参数:它将第一个n-1个参数作为mp3文件连接到一个连接的mp3文件中,该文件由第n个参数给出。例如

mp3join 1.mp3 2.mp3 1-2.mp3 

将1.mp3和2.mp3连接成1-2.mp3

其源代码:

#!/usr/bin/ruby
require "pry"
no_silence=ARGV[0..-2].all?{|z| z =~ /[0-9]{2}/}
binding.pry
open("temp_list000.txt","w") {|f|
  for j in 0..ARGV[0..-2].size-1 do
    i=ARGV[j]
    f.puts "file '#{File.expand_path("~/util/silence-3.5.mp3")}'" if !no_silence && j==0
    f.puts "file '#{i}'" 
    f.puts "file '#{File.expand_path("~/util/silence-3.5.mp3")}'" if !no_silence
  end
}  
system "ffmpeg -safe 0 -f concat -fflags +genpts -i temp_list000.txt -c copy #{ARGV.last}"

在源代码中可以看到,在某些情况下,它会插入3.5秒的“静音”文件。

当我尝试通过以下方式使用bash时出现问题:

mp3join $(ruby -e 'require "shellwords";print Dir["CD02/*"].sort.map{|z| Shellwords.shellescape(z)}.join(" ")') cd2.mp3

在这种情况下,它会失败,因为CD02目录中的mp3文件的文件名中包含空格:

>ls CD02/
'Track No01.mp3'  'Track No10.mp3'  'Track No19.mp3'  'Track No28.mp3'  'Track No37.mp3'  'Track No46.mp3'
'Track No02.mp3'  'Track No11.mp3'  'Track No20.mp3'  'Track No29.mp3'  'Track No38.mp3'  'Track No47.mp3'
'Track No03.mp3'  'Track No12.mp3'  'Track No21.mp3'  'Track No30.mp3'  'Track No39.mp3'  'Track No48.mp3'
'Track No04.mp3'  'Track No13.mp3'  'Track No22.mp3'  'Track No31.mp3'  'Track No40.mp3'  'Track No49.mp3'
'Track No05.mp3'  'Track No14.mp3'  'Track No23.mp3'  'Track No32.mp3'  'Track No41.mp3'  'Track No50.mp3'
'Track No06.mp3'  'Track No15.mp3'  'Track No24.mp3'  'Track No33.mp3'  'Track No42.mp3'  'Track No51.mp3'
'Track No07.mp3'  'Track No16.mp3'  'Track No25.mp3'  'Track No34.mp3'  'Track No43.mp3'
'Track No08.mp3'  'Track No17.mp3'  'Track No26.mp3'  'Track No35.mp3'  'Track No44.mp3'
'Track No09.mp3'  'Track No18.mp3'  'Track No27.mp3'  'Track No36.mp3'  'Track No45.mp3'

当我的mp3join脚本在“ binding.pry”处暂停时,我可以看到解析的命令行参数,在以前的情况下,我的ARGV包含以下内容:

["CD02/Track\\",
 "No01.mp3",
 "CD02/Track\\",
 "No02.mp3",
 "CD02/Track\\",
 "No03.mp3",
 "CD02/Track\\",
 "No04.mp3",
 "CD02/Track\\",
 "No05.mp3",
 "CD02/Track\\",
 "No06.mp3",
 "CD02/Track\\",
 "No07.mp3",
.
.
.

当我简单地发出:

echo $(ruby -e 'require "shellwords";print Dir["CD02/*"].sort.map{|z| Shellwords.shellescape(z)}.join(" ")')

通常会打印:

CD02/Track\ No01.mp3 CD02/Track\ No02.mp3 CD02/Track\ No03.mp3 CD02/Track\ No04.mp3 CD02/Track\ No05.mp3 CD02/Track\ No06.mp3 CD02/Track\ No07.mp3 CD02/Track\ No08.mp3 CD02/Track\ No09.mp3 CD02/Track\ No10.mp3 CD02/Track\ No11.mp3 CD02/Track\ No12.mp3 CD02/Track\ No13.mp3 CD02/Track\ No14.mp3 CD02/Track\ No15.mp3 CD02/Track\ No16.mp3 CD02/Track\ No17.mp3 CD02/Track\ No18.mp3 CD02/Track\ No19.mp3 CD02/Track\ No20.mp3 CD02/Track\ No21.mp3 CD02/Track\ No22.mp3 CD02/Track\ No23.mp3 CD02/Track\ No24.mp3 CD02/Track\ No25.mp3 CD02/Track\ No26.mp3 CD02/Track\ No27.mp3 CD02/Track\ No28.mp3 CD02/Track\ No29.mp3 CD02/Track\ No30.mp3 CD02/Track\ No31.mp3 CD02/Track\ No32.mp3 CD02/Track\ No33.mp3 CD02/Track\ No34.mp3 CD02/Track\ No35.mp3 CD02/Track\ No36.mp3 CD02/Track\ No37.mp3 CD02/Track\ No38.mp3 CD02/Track\ No39.mp3 CD02/Track\ No40.mp3 CD02/Track\ No41.mp3 CD02/Track\ No42.mp3 CD02/Track\ No43.mp3 CD02/Track\ No44.mp3 CD02/Track\ No45.mp3 CD02/Track\ No46.mp3 CD02/Track\ No47.mp3 CD02/Track\ No48.mp3 CD02/Track\ No49.mp3 CD02/Track\ No50.mp3 CD02/Track\ No51.mp3

当我通过调用mp3join脚本将此结果替换为命令行时:

mp3join CD02/Track\ No01.mp3 CD02/Track\ No02.mp3 CD02/Track\ No03.mp3 CD02/Track\ No04.mp3 CD02/Track\ No05.mp3 CD02/Track\ No06.mp3 CD02/Track\ No07.mp3 CD02/Track\ No08.mp3 CD02/Track\ No09.mp3 CD02/Track\ No10.mp3 CD02/Track\ No11.mp3 CD02/Track\ No12.mp3 CD02/Track\ No13.mp3 CD02/Track\ No14.mp3 CD02/Track\ No15.mp3 CD02/Track\ No16.mp3 CD02/Track\ No17.mp3 CD02/Track\ No18.mp3 CD02/Track\ No19.mp3 CD02/Track\ No20.mp3 CD02/Track\ No21.mp3 CD02/Track\ No22.mp3 CD02/Track\ No23.mp3 CD02/Track\ No24.mp3 CD02/Track\ No25.mp3 CD02/Track\ No26.mp3 CD02/Track\ No27.mp3 CD02/Track\ No28.mp3 CD02/Track\ No29.mp3 CD02/Track\ No30.mp3 CD02/Track\ No31.mp3 CD02/Track\ No32.mp3 CD02/Track\ No33.mp3 CD02/Track\ No34.mp3 CD02/Track\ No35.mp3 CD02/Track\ No36.mp3 CD02/Track\ No37.mp3 CD02/Track\ No38.mp3 CD02/Track\ No39.mp3 CD02/Track\ No40.mp3 CD02/Track\ No41.mp3 CD02/Track\ No42.mp3 CD02/Track\ No43.mp3 CD02/Track\ No44.mp3 CD02/Track\ No45.mp3 CD02/Track\ No46.mp3 CD02/Track\ No47.mp3 CD02/Track\ No48.mp3 CD02/Track\ No49.mp3 CD02/Track\ No50.mp3 CD02/Track\ No51.mp3 cd2.mp3

然后它将按预期工作,并且我的ARGV包含:

["CD02/Track No01.mp3",
 "CD02/Track No02.mp3",
 "CD02/Track No03.mp3",
 "CD02/Track No04.mp3",
 "CD02/Track No05.mp3",
 "CD02/Track No06.mp3",
 "CD02/Track No07.mp3",
 "CD02/Track No08.mp3",
 "CD02/Track No09.mp3",
.
.
.

由于按预期方式解析了命令行参数,因此它们由空格分隔,而不是由转义空格分隔。

当我通过以下方式调用连接脚本时,会出现完全相同的问题:

mp3join $(ruby -e 'print Dir["CD02/*"].sort.map{|z| "\"#{z}\""}.join(" ")') cd2.mp3

我的问题是:我应该使用哪种shell命令替换方法代替$(...)来获得正确替换的结果?

0 个答案:

没有答案