2010-10-19 124 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 ///_};完成