我有一个包含文件列表的文件:
02 of Clubs.eps
02 of Diamonds.eps
02 of Hearts.eps
02 of Spades.eps
...
我正在尝试将这些转换为多种尺寸的png格式。我用来做这个的脚本是:
while read -r line
do
for i in 80 35 200
do
convert $(sed 's/ /\\ /g' <<< Cards/${line}) -size ${i}x${i} ../img/card/$(basename $(tr ' ' '_' <<< ${line} | tr '[A-Z]' '[a-z]') .eps)_${i}.png;
done
done < card_list.txt
然而,这不起作用,显然试图拆分每个单词,导致以下错误输出:
convert: unable to open image `Cards/02\': No such file or directory @ error/blob.c/OpenBlob/2514.
convert: no decode delegate for this image format `Cards/02\' @ error/constitute.c/ReadImage/532.
convert: unable to open image `of\': No such file or directory @ error/blob.c/OpenBlob/2514.
convert: no decode delegate for this image format `of\' @ error/constitute.c/ReadImage/532.
convert: unable to open image `Clubs.eps': No such file or directory @ error/blob.c/OpenBlob/2514.
如果我将转换更改为echo,结果看起来正确,如果我复制一行并在shell中自己运行它可以正常工作:
convert Cards/02\ of\ Clubs.eps -size 80x80 ../img/card/02_of_clubs_80.png
convert Cards/02\ of\ Clubs.eps -size 35x35 ../img/card/02_of_clubs_35.png
convert Cards/02\ of\ Clubs.eps -size 200x200 ../img/card/02_of_clubs_200.png
convert Cards/02\ of\ Diamonds.eps -size 80x80 ../img/card/02_of_diamonds_80.png
convert Cards/02\ of\ Diamonds.eps -size 35x35 ../img/card/02_of_diamonds_35.png
convert Cards/02\ of\ Diamonds.eps -size 200x200 ../img/card/02_of_diamonds_200.png
convert Cards/02\ of\ Hearts.eps -size 80x80 ../img/card/02_of_hearts_80.png
convert Cards/02\ of\ Hearts.eps -size 35x35 ../img/card/02_of_hearts_35.png
convert Cards/02\ of\ Hearts.eps -size 200x200 ../img/card/02_of_hearts_200.png
convert Cards/02\ of\ Spades.eps -size 80x80 ../img/card/02_of_spades_80.png
更新
只是添加引号(见下文)与上面的结果相同,我一直在使用sed添加反斜杠
convert '"'Cards/${line}'"' -size ${i}x${i} ../img/card/$(basename $(tr ' ' '_' <<< ${line} | tr '[A-Z]' '[a-z]') .eps)_${i}.png;
我尝试了双引号和单引号
答案 0 :(得分:3)
Shell可以正常分割行,并使用变量使代码可读 - 避免使用水平滚动条...
while read -r line
do
for i in 80 35 200
do
epsfile="Cards/$line"
pngbase=$(basename "$line" .eps | tr ' A-Z' '_a-z')
pngfile="../img/card/${pngbase}_${i}.png"
convert "$epsfile" -size ${i}x${i} "$pngfile"
done
done < card_list.txt
如果必须处理包含空格的文件名,则需要在将名称传递给命令时将其用双引号括起来。将所有文件操作压缩成一行的复杂代码几乎无法读取。您可以在一个命令中完成整个音译,如上所示,这也简化了事情。
即使80个字符不是硬限制,但值得将其保持为粗略限制,因为如果行更长,则可能无法读取,并且代码必须可读且易于维护。
答案 1 :(得分:2)
只需引用带有空格或其他特殊字符的文件名即可。此外,您不需要sed或tr。
请参阅关于“变量替换”的bash文档(pps 21-22,bash Pocket Reference,O'Reilly)
通过将转换逻辑放入函数
来简化循环# cvt file size
cvt() {
infile="$1" # quote in case filename has blanks
size="$2"
outfile="${infile/ /_}" # replace spaces with underlines
outfile="${outfile##*/}" # remove any directory path
outfile="${outfile,,*}" # downcase the filename
outfile="${outfile%.eps}_$size.png" # remove suffix, add size and new suffix
( set -x ; convert "Cards/$infile" -size ${size}x$size "../img/card/$outfile" )
}
while read -r line ; do
for i in 80 35 200 ; do
cvt "$line" $i
done
done < card_list.txt
答案 2 :(得分:1)
像Hai说的那样,将文件名括在“”中。否则,shell将读取行上的空格作为下一个参数的分隔符。
例如
VAR="test file"
cat $VAR # outputs the contents of 'test', followed by the contents of 'file'
cat "$VAR" # outputs the contents of 'test file'
编辑: 简而言之,你的问题是使用sed来逃避空间。它没有做你正在考虑的事情 - 它正在产生文字字符串“02 \ of \ Clubs.eps”而不是“02. of Clubs.eps”。用“Cards / $ {line}”替换sed部分。