2011-05-20 56 views
2

我正在創建一個bash shell腳本,它將重命名文件擴展名而不必指定舊的文件擴展名。如果我在Linux中輸入「change foo *」到終端,它會將所有文件擴展名更改爲foo。重命名文件擴展名而不指定

所以我們可以說我有四個文件:「file1.txt」,「file2.txt.txt」,「file3.txt.txt.txt」和「file4」。

當我運行命令,這些文件應該是這樣的: 「file1.foo」, 「file2.txt.foo」, 「file3.txt.txt.foo」 和 「file4.foo」

有人可以看我的代碼並糾正它。如果有人能爲我實現這一點,我也會很感激。

#!/bin/bash 

    shift 

    ext=$1 

    for file in "[email protected]" 
    do 
     cut=`echo $FILE |sed -n '/^[a-Z0-9]*\./p'` 
     if test "${cut}X" == 'X'; then 
      new="$file.$ext" 
     else 
      new=`echo $file | sed "s/\(.*\)\..*/\1.$ext/"` 
     fi 
     mv $file $new 
    done 
    exit 
+1

你跟例如做什麼'important.files.tar.gz.gpg'(重要文件加密gzip壓縮的tar球)?它會變成'important.foo','important.files.foo','important.files.tar.foo','important.files.tar.gz.foo'或'important.files.tar.gz.gpg .foo'? – 2011-05-20 07:57:49

+0

它應該變成「important.files.tar.gz.foo」。 – 2011-05-20 18:11:46

回答

5
  • 始終使用周圍變量取代,例如雙引號echo "$FILE"而不是echo $FILE。如果沒有雙引號,shell會在變量的值中擴展空格和水平字符(\[*?)。 (有些情況下,你不需要引號,有時候你需要分詞,但是這是爲了將來的課程。)
  • 我不確定你想用sed來做什麼,但不管它是什麼是的,我相信它在shell中是可行的。
    • 要檢查是否$FILE包含一個圓點:case "$FILE" in *.*) echo yes;; *) echo no;; esac
    • $FILE剝去最後延伸:${FILE%.*}。例如,如果$FILEfile1.txt.foo,則產生file1.txt。更一般地,${FILE%SOME_PATTERN}擴展爲$FILE,其中最短的後綴匹配SOME_PATTERN剝離。如果沒有匹配的後綴,則擴展爲$FILE未更改。變體${FILE%%SOME_PATTERN}刪除最長的後綴。同樣,${FILE#SOME_PATTERN}${FILE##SOME_PATTERN}剝去一個後綴。
  • test "${TEMP}X" == 'X'很奇怪。這看起來像是過去的一個誤會。正常的寫作方式是[ "$TEMP" = "" ][ -z "$TEMP" ]。使用==而不是=是一個bash擴展。如果$TEMP看起來像是一個操作員,但是這些已經不再適用於恐龍,並且即使如此,X也需要開始,因爲有問題的操作員以-開頭:[ "X$TEMP" == "X" ]
  • 如果文件名以-開頭,mv將認爲它是一個選項。使用--來說「這就是它,沒有更多的選項,以下是操作數」:mv -- "$FILE" "$NEW_FILE"
  • 這是非常次要的,但常見的(不是通用的)慣例是對於內部腳本變量使用大寫字母來表示環境變量和小寫字母。
  • 由於您只使用標準外殼功能,因此您可以使用#!/bin/sh啓動腳本(當然也可以使用#!/bin/bash)。
  • exit腳本的末尾是沒用的。

應用所有這些,這裏是最終的腳本。

#!/bin/sh 
ext="$1"; shift 
for file in "[email protected]"; do 
    base="${file%.*}" 
    mv -- "$file" "$base.$ext" 
done 
+0

非常感謝Gilles。這是非常有用的信息!我需要根據您在帖子中提到的內容編輯我的代碼。 – 2011-05-20 18:14:51

+0

+1:很好的解釋。 – Johnsyweb 2011-05-24 01:45:05

+0

+1:美麗而詳細的解釋。再加上不錯的例子 – 2011-05-24 02:03:20

1

不完全是你在問什麼,但看看perl rename實用程序。很強大! man rename是一個好的開始。

+0

是的,我意識到這一點,但我創建此代碼作爲練習的一部分。 – 2011-05-20 18:12:46

0

對我來說,這個工作

for FILE in `ls` 
do 
NEW_FILE=${FILE%.*} 
NEW_FILE=${NEW_FILE}${EXT} 
done 

我只是想告訴NEW_FILE=${FILE%.*}
這裏NEW_FILE獲取文件名作爲輸出。你可以隨意使用它。
我在bash測試與uname -a = "Linux 2.4.20-8smp #1 SMP Thu Mar 13 17:45:54 EST 2003 i686 i686 i386 GNU/Linux"

+2

不要使用那樣的'ls'。在*中使用'FILE',否則如果文件名有空格則會失敗。 – 2011-05-20 08:00:11

+1

[爲什麼你不應該解析ls的輸出](http://mywiki.wooledge.org/ParsingLs)。 – Gilles 2011-05-20 12:00:55

+0

**其實它清楚地提到了我想分享的內容。**這是'我只想告訴NEW_FILE = $ {FILE%。*}'。其餘的都是小菜一碟。我相信OP非常想要這個東西。否則,他在'$ @「' – Mayank 2011-05-20 12:06:57

相關問題