序言: 所以我有一个项目,我需要在一堆文件上运行转换工具。转换有多个步骤,可能需要一段时间。由于这些文件不一定在同一目录中,因此我创建了一个文件文件,其中包含要转换的文件名:
<filenames.txt>
/home/me/Documents/file1.txt
/home/me/Documents/file2.txt
/home/me/Documents/file3.txt
问题: 然后我有一个bash脚本来运行这些文件,并执行转换步骤。但是,我尝试回显相位和文件名,回声,在这种情况下,将回声文本粘贴在文件名的中间:
<script.sh>
cat filenames.txt | while read some_file
do
echo
echo "Begin FORMAT_A to FORMAT_B conversion..."
echo "FORMAT_A Filename:"
echo $some_file
formatb_dir= dirname $some_file | tr '\n' "/"
formatb_file= basename $some_file ".xml" | tr '\n' "_"
formatb=$formatb_dir$formatb_file"form_b.xml\n"
echo "FORMAT_B Filename:"
echo $formatb
done
生成如下输出:
Begin FORMAT_A to FORMAT_B conversion...
FORMAT_A Filename:
/home/me/Documents/file1.txt
/home/me/Documents/file1.txt_FORMAT_B Filename:
form_b.xml
Begin FORMAT_A to FORMAT_B conversion...
FORMAT_A Filename:
/home/me/Documents/file2.txt
/home/me/Documents/file2.txt_FORMAT_B Filename:
form_b.xml
Begin FORMAT_A to FORMAT_B conversion...
FORMAT_A Filename:
/home/me/Documents/file3.txt
/home/me/Documents/file3.txt_FORMAT_B Filename:
form_b.xml
“FORMAT_B Filename”,echo'd文本,出现在附加文本“form_b.xml”之前。
我查看了dirname,basename,echo和tr的手册页,但我没有看到任何看起来像是因为我看到的东西。我试着在谷歌上四处看看,但我不确定我是否在问正确的问题(“bash echo text before variable”?)。
问题:为什么我的回音将回声文本放在变量的中间?
(可能相关的问题:“我是以完全错误的方式做我正在做的事情吗?”)
编辑:我接受了fortea的答案,因为它让我了解了我对变量的不了解以及从命令中获取输出。也就是说,dogbane和Jonathan Leffler表现出更好的方式来做我正在做的事情。
答案 0 :(得分:2)
问题在于变量声明:
formatb_dir= dirname $some_file | tr '\n' "/"
formatb_file= basename $some_file ".xml" | tr '\n' "_"
formatb=$formatb_dir$formatb_file"form_b.xml\n"
尝试换行:echo $formatb_dir
:它不包含任何内容,因为在'='之后会有一个空格。然后bash读取dirname $somefile |tr '\n' "/"
并执行此命令。创建formatb_file时也一样,但这次命令是basename。 (这是“FORMAT_B文件名:”之前出现的内容)。
然后正确创建formatb,但$ formatb_dir和$ formatb_file为空,因此$ formatb将仅包含"form_b.xml\n"
。
然后你回显“FORMAT_B文件名:”。
然后你回显$ formatb,它将输出“form_b.xml”。
所以,你应该使用这样的东西:
formatb_dir=$(dirname $some_file | tr '\n' "/")
formatb_file=$(basename $some_file ".xml" | tr '\n' "_")
formatb=$formatb_dir$formatb_file"form_b.xml\n"
阅读here
答案 1 :(得分:2)
问题在于您运行的命令如dirname
和basename
,环境设置为奇数,而不是捕获输出。也就是说,如果你运行:
env_var=some_value commandname arg1 arg2
运行程序commandname
时环境变量$env_var
设置为some_value
(仅适用于此命令)。在您的代码中,您写道:
formatb_dir= dirname $some_file | tr '\n' "/"
这与我给出的例子是同构的。它运行命令dirname
,环境变量formatb_dir
设置为空字符串(dirname
完全忽略此项),然后将dirname
的输出发送到tr
}和tr
的输出到标准输出。
$(...)
捕获输出。我不打算将dirname
输出末尾的换行符映射到斜杠,或将basename
输出末尾的换行符映射到下划线。您可以在生成的名称中添加斜杠和下划线。
修正:
cat filenames.txt |
while read some_file
do
echo
echo "Begin FORMAT_A to FORMAT_B conversion..."
echo "FORMAT_A Filename:"
echo $some_file
formatb_dir=$(dirname "$some_file")
formatb_file=$(basename "$some_file" ".xml")
formatb="${formatb_dir}/${formatb_file}_form_b.xml"
echo "FORMAT_B Filename:"
echo $formatb
done
formatb
的分配使用${varname}
两次来保持一致性;只有在${formatb_file}
扩展时才需要括号。
答案 2 :(得分:1)
这是因为您正在使用tr
并删除\n
字符。
为什么不简单地将字符串连接在一起而不是使用tr
?
formatb_dir="$(dirname ${some_file})"
formatb_file="$(basename ${some_file})"
formatb="${formatb_dir}/${formatb_file}_form_b.xml"
echo "FORMAT_B Filename: $formatb"