作者 主題: 有關將目錄中的所有檔案都轉成小寫(包含子目錄)  (閱讀 7544 次)

0 會員 與 1 訪客 正在閱讀本文。

大白

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
目錄中有大小寫,我想要將此目錄中的所有檔案都轉成小寫(包含子目錄),請問
要如何達成呢?以下script似乎只能轉換第一層目錄。

 #!/bin/bash
     file=ls .
     for i in $file
     do
          lowwer=`echo $i |tr 'A-Z' 'a-z'`
          mv $i $lowwer
     done

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
引述: "小飛俠"
目錄中有大小寫,我想要將此目錄中的所有檔案都轉成小寫(包含子目錄),請問
要如何達成呢?以下script似乎只能轉換第一層目錄。

 #!/bin/bash
     file=ls .
     for i in $file
     do
          lowwer=`echo $i |tr 'A-Z' 'a-z'`
          mv $i $lowwer
     done

把 ls 改成 find。
先用 find -type d  把目錄都改成小寫,
再用 fine -type f 把所有檔案也改成小寫的。

大白

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
這是我做的一些修改,但執行後,發現一些問題,如 有一目錄 DESK/Test/LIGHT 要變成 desk/test/light
mv DESK/Test/LIGHT desk/test/light 這語法不符呢!

#!/bin/bash
     file=`find . -type f|sed 's/^..//'`
     dir=`find . -type d|sed 's/^..//'`

     for i in $file
     do
          lowwer=`echo $i |tr 'A-Z' 'a-z'`
          mv $i $lowwer
     done
     for i in $dir
     do
          lowwer=`echo $i |tr 'A-Z' 'a-z'`
          mv $i $lowwer
     done

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
引述: "thyme"

把 ls 改成 find。
先用 find -type d  把目錄都改成小寫,
再用 fine -type f 把所有檔案也改成小寫的。

大白

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
感謝版主回應,我先前也有試過先用find -type d而後 find -type f,但我覺得問題好像不是出在這裡,例如假設有一資料夾 /FIR  其中包含了 SEC目錄,而SEC目錄中又包含THR目錄,所以完整路徑為 /FIR/SEC/THR ,在linux 中好像無法直接執行以下指令  #mv /FIR/SEC/THR /fir/sec/thr 所以出現error message。

mv: cannot move ‘/FIR/SEC/THR’ to ‘/fir/sec/thr’: 沒有此一檔案或目錄

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
恩. 要注意的問題還是要小心處理.
1) 碰到有 space 的 file name, 可能丟到 for loop 裡就變樣了.
2) 最好加上決對路徑, 然後 cd 到最後一層目錄, 然後再 mv .

kenduest

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3675
    • 檢視個人資料
    • http://kenduest.sayya.org
引述: "小飛俠"
感謝版主回應,我先前也有試過先用find -type d而後 find -type f,但我覺得問題好像不是出在這裡,例如假設有一資料夾 /FIR  其中包含了 SEC目錄,而SEC目錄中又包含THR目錄,所以完整路徑為 /FIR/SEC/THR ,在linux 中好像無法直接執行以下指令  #mv /FIR/SEC/THR /fir/sec/thr 所以出現error message。

mv: cannot move ‘/FIR/SEC/THR’ to ‘/fir/sec/thr’: 沒有此一檔案或目錄


看一下 basename 與 dirname 這兩個程式用法會有幫助。

==
I am kenduest - 小州

my website: http://kenduest.sayya.org/

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
試試看:
代碼: [選擇]
#!/bin/bash
#
# to lower filename case in a dir and all it's sub dirs.
#

# only one argument is acceptable.
[ "$#" -ne 1 ] && {
        echo Usage: $0 /path/to/dir
        exit 1
}

# argument must be a directory
[ -d $1 ] || {
        echo Error: $1 is not a directory.
        exit 2
}

dir=$1

# reset IFS to avoid space in filenames
old_IFS="$IFS"
IFS='
'

# function to rename filename to lowercase
lowcase() {
        # do nothing if original filename is lowercase
        [ "$1" = "$2" ] || {
                mv $1 $2
        }
}

# function to list all files
listfile() {
        while [ "$1" ];
        do
                # to have new named in lowercase
                n_file=$(echo $1 | tr A-Z a-z)

                # rename dir then enter dir
                if [ -d $1 ]; then
                        lowcase $1 $n_file
                        cd $n_file

                        # do recursive
                        listfile $(ls)

                        # return to upper dir
                        cd ..
                else
                        lowcase $1 $n_file
                fi
                shift 1
        done
}

cd $dir
listfile *

exit 0

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
代碼: [選擇]

$ cat ../uppercase.sh
mkdir ./SBg
mkdir ./SBg/Ed
mkdir ./SBg/Ed/SBVTHR
mkdir ./SBg/Ed/SBVTHR/SB0
touch ./SBg/Ed/c83k
mkdir ./yhs
mkdir ./yhs/uid
mkdir ./yhs/uid/THR
touch ./yhs/uid/NH
mkdir ./yhs/HG
touch ./yhs/tr
mkdir ./FIR
mkdir ./FIR/SEC
mkdir ./FIR/SEC/THR
mkdir ./FIR/uid
touch ./FIR/uid/THR
touch ./FIR/BG
touch ./FIR/wc
$ ../uppercase.sh
$ cat ../low.sh
#!/bin/bash
find * -depth | while read name;
do
        # get basname
        fname=${name##*/}
        # get lowwer case name
        lowfname=`echo $fname|tr 'A-Z' 'a-z'`
        # lowwercase already
        [ "$fname" = "$lowfname" ] && continue
        if [ "$fname" != "$name" ]; then
                #get dirname
                dname=${name%/*}
                echo "mv $name $dname/$lowfname"
                mv $name $dname/$lowfname
        else
                # no dirname
                echo "mv $name $lowfname"
                mv $name $lowfname
        fi
done
$ ../low.sh
mv FIR/SEC/THR FIR/SEC/thr
mv FIR/SEC FIR/sec
mv FIR/uid/THR FIR/uid/thr
mv FIR/BG FIR/bg
mv FIR fir
mv SBg/Ed/SBVTHR/SB0 SBg/Ed/SBVTHR/sb0
mv SBg/Ed/SBVTHR SBg/Ed/sbvthr
mv SBg/Ed SBg/ed
mv SBg sbg
mv yhs/uid/THR yhs/uid/thr
mv yhs/uid/NH yhs/uid/nh
mv yhs/HG yhs/hg
$ find *
fir
fir/bg
fir/uid
fir/uid/thr
fir/wc
fir/sec
fir/sec/thr
sbg
sbg/ed
sbg/ed/c83k
sbg/ed/sbvthr
sbg/ed/sbvthr/sb0
yhs
yhs/uid
yhs/uid/nh
yhs/uid/thr
yhs/tr
yhs/hg

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
thyme 兄的 code 很好!
不過最好能照顧到 "My Document" 這樣的 file name, 也就是有 space 在裡面.
只要將 IFS 修改一下, 就好了...  ^_^

大白

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
謝謝各位的回應及提醒,我這兩天也有用比較笨的方式寫了一個script,內容如下
使用複製的想法....將轉換好小寫的目錄、檔案存到/tmp/lower目錄中,不過此script先決條件必須存在想要轉換的目錄中..

#!/bin/bash
export LANG=zh_TW.Big5
#搜尋此目錄中的"目錄"及"檔案"名稱存到/root/transfer.dir /root/transfer.file
find -type d |sed 's/^..//'|sed '/^\./d' > /root/transfer.dir
find -type f |sed 's/^..//'|sed '/^\./d' > /root/transfer.file

#產生的結果會存到/tmp/lower目錄中,所以先將建立此目錄
rm -rf /tmp/lower
mkdir /tmp/lower


#將搜尋到的目錄名稱,轉換小寫存到/tmp/lower目錄中
declare -i wc1=1
#計算出剛才搜尋到的目錄名稱的數量
wc=`wc -l /root/transfer.dir|sed '1,$s/^ *//'|cut -d " " -f 1`
wc=`expr "$wc" + 1`

until [ "$wc1"  = "$wc" ]
do
        #將剛才搜尋到的目錄名稱一個一個的轉換成小寫名稱,而後使用mkdir建立小寫名稱目錄
        dest=`sed -n "$wc1"p /root/transfer.dir |tr 'A-Z' 'a-z'`
        mkdir -p /tmp/lower/"$dest"

        wc1=$wc1+1
done



#將搜尋到的檔案名稱,轉換小寫存到/tmp/lower目錄中
declare -i wc1=1
#計算出剛才搜尋到的檔案名稱的數量
wc=`wc -l /root/transfer.file|sed '1,$s/^ *//'|cut -d " " -f 1`
wc=`expr "$wc" + 1`

until [ "$wc1"  = "$wc" ]
do
        #將剛才搜尋到的檔案名稱一個一個的轉換成小寫名稱,而後使用cp複製原始檔案
        sour=`sed -n "$wc1"p /root/transfer.file`
        dest=`sed -n "$wc1"p /root/transfer.file |tr 'A-Z' 'a-z'`
        cp "$sour" /tmp/lower/"$dest"

        wc1=$wc1+1
done
rm -rf /tmp/lower/transfer-lower.sh