怎樣寫 bash 腳本批量重命名文件?
將一個文件夾里所有" glyphicons_數字_字元串.png "這樣的文件重命名為" 字元串.png ",即去掉黑色斜體部分的文件名內容,用shell命令或腳本怎麼實現?
Debian/Ubuntu 自帶一個叫做 rename 的 Perl 腳本,用法如下:
$ rename "s/^glyphicons_[0-9]+_//" glyphicons_*.png
Mac 用戶可以用這個改進版:
$ brew install rename
#!/bin/bash
#path變數指向你的目標目錄,找好目標目錄並取消下方行的注釋#path=/your/dirfor i in `ls $path | grep "^glyphicons_[0-9]*_.*.png$"`do name=`echo $i | sed "s/^glyphicons_[0-9]*_//g"` mv $i $namedone#如有錯誤,請指出,謝謝$ ls -1 glyphicons_[0-9]*.png|sed "s/glyphicons_([0-9][0-9]*)_(.*).png/mv 2.png/"|sh -v
正則表達式是一切字元串處理的基礎,掌握它,一切字元串問題迎刃而解。
自己搞定了~_~! 雖然很搓,但希望能拋磚引玉。。。
#!/bin/sh
# generate files
# for debug
#`ls | grep glyphicons &> input`
# for debug
#i=`cat "input"`
i=`ls | grep glyphicons`
set -x
# for debug
# note: echo "" &> temp is not an empty file
# use `od -c temp` to check out
`cat /dev/null &> temp`
for j in $i
do
a=${j//_/ }
#echo $a
c=0
s=""
so=""
for k in $a
do
if [ $c == 0 ]; then
so=$k
elif [ $c == 1 ]; then
so=$so"_"$k
elif [ $c == 2 ]; then
so=$so"_"$k
s=$s$k
else
so=$so"_"$k
s=$s"_"$k
fi
c=`expr $c + 1`
done
# for debug
echo "mv -i $so $s" &>&> temp
`mv -i $so $s`
done
zsh 湊個熱鬧:
zmv "glyphicons_*_(*).png" "$1.png"
如果最後的字元串沒有重複的話
for i in `ls|grep glyphicons`
do
newName=`echo $i |cut -d_ -f3`
mv $i $newName
done
純粹使用bash內置命令的話,一行命令就夠了:
==================建立測試文件====================$ touch glyphicons_315911_linux{a..g}.png
$ ls *.png
glyphicons_315911_linuxa.png glyphicons_315911_linuxe.png
glyphicons_315911_linuxb.png glyphicons_315911_linuxf.png
glyphicons_315911_linuxc.png glyphicons_315911_linuxg.png
glyphicons_315911_linuxd.png
==================運行腳本========================
$ for i in `ls glyphicons_*.png`; do mv $i ${i##glyphicons_*_}; done
$ ls *.png
linuxa.png linuxc.png linuxe.png linuxg.png
linuxb.png linuxd.png linuxf.png
#最後刪除測試文件,此命令請謹慎使用
$ rm -f *.png
隨手寫的,把當前目錄下文件名中含有的某個單詞換成另一個,你把目標單詞換成空就是了。沒有做找不到文件的處理,自己可以加一下。
#!/bin/sh
# This script is used to change the input current_word in names of files to appointed word.
if [ $# -ne 2 ];then
echo Usage: sh $0 current_word target_word
exit
fi
current_word=$1
target_word=$2
for file_name in $(ls)
do
target_name=$(echo ${file_name} | sed "s/${current_word}/${target_word}/g")
mv ${file_name} ${target_name}
done
# ls
glyphicons_123456_a.png glyphicons_123456_b.png glyphicons_123456_c.png glyphicons_123456_d.png glyphicons_123456_e.png
# ls |awk -F"_" "{print "mv " $1"_"$2"_"$3 " " $3}"|bash
===
改良了一下。
ls|awk -F"_" "{print "mv " $0 " " $3}"|bash
+++++20170627再改。剛剛看見有夥伴點贊,然後看了下評論上面的答案我也不知道當時怎麼想的。。加了個 。。。直接下面這樣就可以了。把 直接換成空格。
ls|awk -F"_" "{print "mv " $0 " " $3}"|bash
rename 『glyphicons_數字_』 『』 *
有個rename命令,跟sed的s用法一樣
前面的好多解答追求短小快的太多,其中不乏技巧,但是從一個程序員的角度看,沒有注意一些細節。
1. 規則不夠準確, 比如glyphicons_*.png的情況,如果遇到glyphicons_1a_A.png的文件,也就是在兩個"_"中間部分不完全是數字的情況,按照樓主的要求,它不滿足條件,但該規則會認為滿足. 同樣道理上面的sed也是同樣問題。
如果使用
sed -E "s/glyphicons_[0-9]*_//"
應該會好些,「*」說明中間的數字可以出現多次,但不能有非數字元號。
當然這一點也有題主說明不太清楚的地方
2. 實際情況考慮不周,比如有兩個文件名:
glyphicons_0_same.png
glyphicons_1_same.png
它們可以在同一個目錄下共存,因為文件名不同,當去除前面的的部分後,剩下的部分都是same.png,也就是同名文件,如果使用mv命令,因為是移動到同一個目錄下,那麼先被移動的就會被後面的覆蓋。
沒有用過rename和zsh,所以不知道它們是如何處理同名文件的。
所以,看起來需要更多的語句處理衝突。我這裡不寫了,因為寫出來的肯定沒有他人寫得漂亮。
之所以說上面這些,不是說前面的答案不好,其實它們有體現了shell命令的簡介的風格,而且用多種方式達成一個目的,看上去賞心悅目。但在實際處理中需要考慮多種的因素,否則出現數據丟失或者莫名其妙的結果。
推薦閱讀:
※mysql中的一個數據表,共有14萬行左右,其中一列是公式,怎麼把每一個公式導出成一個txt文件?
※幹了四年運維,但是都是初級的,現在想學 Linux 運維,不知道馬哥和老男孩哪個做得更好一些?
※Ubuntu server 14.04 需要經常 update 嗎?
※運維工程師和架構師區別?
※為什麼很多公司都自主開發監控系統?(Linux運維方面)