2010-10-19 130 views
12

我正在尝试编写脚本,它将裁剪大尺寸照片并将其调整为高清壁纸。BASH中带空格的文件名

#! /bin/bash 


for i in `ls *.jpg` 
do 
    width=`identify -format '%w' $i` 
    height=`identify -format '%h' $i` 

    if [ `echo "$width/$height > 16/9" | bc -l` ] 
    then 
     exec `convert $i -resize 1920 -gravity Center -crop '1920x1080+0+0' +repage temp` 
    else 
     exec `convert $i -resize x1080 -gravity Center -crop 1920x1080+0+0 +repage temp` 
    fi 

    rm $i 
    mv temp $i 
done 

但似乎脚本有具有文件名的空格(翻滚Weed.jpg)的问题。我怎样才能解决这个问题?

+2

答案已经在下面给出,但我只想补充说,shell脚本对于处理文件名中的空格非常不利,因为太多的列表是空格分隔的 - 特别是命令参数。例如,尝试通过scp复制带有空间的文件!没有手动转义几乎是不可能的。 – Timmmm 2010-10-19 11:30:10

+2

您应该完整阅读'http:// mywiki.wooledge.org/BashPitfalls' :-)它将大大提高您的bash技能 – Benoit 2010-10-19 16:08:01

回答

20

首先,你不需要ls。通过在backtics中使用ls,您可以隐式地让bash将一个字符串解析为一个列表,并按空格分隔。相反,使bash生成列表并将其分开,而不会出现这种怪癖:

此外,您需要将所有$i用法括在引号中,使bash将其作为整体替换,而不是将字符串拆分为单独的单词。

以下是一个演示这两种思路的脚本:

for i in *.jpg ; do 
    echo "$i"; 
done 
+0

如果文件路径包含空格,则这不起作用。第2行的命令(这种情况下为'echo')将空格解释为参数分隔符。 – Diederik 2014-01-18 11:26:00

+1

@Diederik,嗯,这个在我的shell中用空格工作。将'$ i'包含在句子中是有用的。 – 2014-01-25 05:02:32

+0

你似乎是对的,如果所有的文件都在同一个目录下,即使有空格,它也能工作。当我在for循环中使用'find'时,脚本失败。文件夹名称中的空格跳出了我的脚本。 – Diederik 2014-01-28 18:51:19

0

在文件名周围使用双引号。就像这样:

width=`identify -format '%w' "$i"` 

请注意周围"$i"双引号。

4

我建议写的行这样的:

for i in *.jpg 

并封装在双引号$i"$i"


如果你坚持

`ls *.jpg` 

风格,(如果你比如从一个更复杂的命令让你的文件名),你可以尝试设置IFS\n

IFS='\n' 

比较这两个处决:

$ for f in `ls *`; do echo $f; done 
hello 
world 
test 

$ IFS='\n'; for f in `ls *`; do echo $f; done 
hello world 
test 
14

使用read来规避空间问题。它看起来有点不自然写这样的循环,但它工作得更好:

find . -type f -iname "*.jpg" | while read i 
do 
    # your original code inside the loop using "$i" instead of $i 
done 

-iname你也可以得到,可能有不同的外壳如.jpg扩展名的JPG文件。 “iname”中的“i”表示忽略套管。

+0

这样做会导致名称带有文字反斜杠,带有字面换行符的名称和名称以空白结尾。 – 2015-08-17 21:17:13

+0

为了解决这个问题,在IFS = read -r -d''i'的同时,在'find'中添加'-print0',并使shell结束'; '-r'修复了反斜杠,'-d'''和'-print0'修复了文字换行符,'IFS ='修复了对以空格结尾的名字的支持。 – 2015-08-17 21:17:32

0
#! /bin/bash 
mkfifo ./lsOutput 
ls -1 *.jpg > ./lsOutput 
    while read line 
    do 

    width=`identify -format '%w' "$line"` 
    height=`identify -format '%h' "$line"` 

    if [ `echo "$width/$height > 16/9" | bc -l` ] 
    then 
     exec `convert "$line" -resize 1920 -gravity Center -crop '1920x1080+0+0' +repage temp` 
    else 
     exec `convert "$line" -resize x1080 -gravity Center -crop 1920x1080+0+0 +repage temp` 
    fi 

    rm "$line" 
    mv temp "$line" 
done<./lsOutput 
1

在bash,使用字符串替换找到

$ {字符串//子/换货}

Replace all matches of $substring with $replacement. 

所以这个工程:

找。 -type f -name'*。jpg'|同时阅读我; do/bin/mv -f“$ i”$ {i ///_};完成