2014-08-27 16 views
1

我編寫了一個腳本來一次重命名多個文件並添加前導零。 腳本將第一個參數作爲要重命名的文件,第二個參數是新名稱,第三個參數可以給出新擴展名linux腳本:使用空格對文件進行批量重命名

只要文件不包含空格(test asd 1。 TXT /測試ASD 2.txt),因爲那麼輸出是:

~/Desktop $ gpRenameWithZero test\ asd\* test_ mp3 
ls: cannot access test: No such file or directory 
ls: cannot access asd*: No such file or directory 
ls: cannot access test: No such file or directory 
ls: cannot access asd*: No such file or directory 

下面是腳本:

#!/bin/bash 
#rename a group of files with adding padding zero: gpRenameWithZero $1=filesToBeRenamed $2=newName $3=filetype: gpRenameWithZero \* newName_ jpg 

#123 files -> length of number are 3 digits 
numberOfDigits=$(ls $1| wc -l | xargs expr length) 

#take extension from command line or take from filename 
if [ $# -gt 2 ]; then 
    extension=$3 
else 
    extension=$(ls -rt $1 | head -n 1 | rev | cut -d . -f1 | rev) 
fi 

#Preview 
ls -rt $1 | cat -n | while read n f; do echo mv "$f" `printf "$2%0$numberOfDigits"d".$extension" $n`; done 

read -p "Do you wish to rename [y/n]?" yn 
case $yn in 
    [Yy]*) ls -rt $1 | cat -n | while read n f; do mv "$f" `printf "$2%0$numberOfDigits"d".$extension" $n`; done;; 
    [Nn]*) ;; 
esac 

我已經使用引號試過/雙引述vriables和參數,逃避/不逃避。

如何解決這種情況?還是有一個更簡單的腳本,它將文件重命名,新名稱和擴展名作爲參數)重命名多個文件。

+1

[不要解析'ls'!](http://mywiki.wooledge.org/ParsingLs) – Biffen 2014-08-27 09:28:23

+1

爲什麼不使用'rename'工具?例如,我有時使用'rename's// _/g「*'來刪除我的文件名中的空格 – Emilien 2014-08-27 09:30:35

回答

0

你得到了自己的想法,爲什麼是真的,評論說:不要從ls解析輸出。

在這種情況下,您需要處理以NULL結尾的文件名。這裏有很多命令可以使用這種NULL結尾的字符串。

find命令可以使用arg -print0或精確指定的-print "<format>\0"來輸出以NULL結尾的文件名。

因爲您想按修改時間排序(編號)文件(ls -rt),您需要使用一些技巧。所以

  • find命令(GNU版本)可以打印出文件的修改時間
  • 需要通過這次
  • 對它們進行排序和時間字段的切割後,你將有文件名的排序列表

這例如可以實現與下一個命令:

find . -mindepth 1 -maxdepth 1 -name "*" -printf "%[email protected]:%p\0" |sort -zrn |sed -z 's/[^:]*://' 
                ^^^^^^^^   ^^^   ^^^^^^^^^^ 
modification-time-in-seconds<colon>path-name<NULL>---+    |    | 
      sort the NULL-terminated lines numerically (by time) ---+    | 
       remove the <time><colon> part, so only the filename remains ----------+ 

你可以把上面的到bash的功能,以方便使用,如:

sort_files_by_time() { 
     find "${1:-.}" -mindepth 1 -maxdepth 1 -type f -name "${2:-*}" -printf "%[email protected]:%p\0" | sort -zrn | sed -z 's/[^:]*://' 
} 

上述功能可以採取兩個可選參數:

  1. 目錄名稱查找(默認:。)
  2. 用於細絲名搜索的模式(默認值:*)

現在,您有一個按空格終止按時間排序的文件名列表,並且需要讀取並使用它們。下一個循環

while IFS= read -d $'\0' -r path ; do 
    dir=$(dirname "$path") 
    file=$(basename "$path") 

    #do what you want 

done < <(sort_files_by_time) 

ALWAYS雙引號 「$變量」 什麼可能包含空格。

+0

我注意到,當我用$替換$ 1中的空格時,它會起作用:」gpRenameWithZero test \ asd \\ * test_ mp3「變成」gpRenameWithZero test \\ * asd \\ * test_ mp3「。只是一個解決方法,但我沒有改變我的腳本:) – user328211 2014-08-27 15:59:00

0

在Unix中,命令行參數的通配符擴展由shell執行 - 在傳遞給程序之前。

即使文件名中沒有空格,該腳本也不起作用。例如,如果有三個文件song1.mp3song_2.MP3song_0003.mpeg3,運行gpRenameWithZero song* test_ mp3腳本將被傳遞五個參數:$ 1將 「song1.mp3」,$ 2將「song_0003 .mpeg3「,3美元將是」song_2.MP3「,4美元將是」test_「,5美元將是」mp3「。所以你的腳本中的$ 1並不是你所期望的。

將新的文件名前綴和擴展名作爲第一個和第二個參數對待,然後剩下的參數(不管有多少個)將是文件名。更高級的解決方案甚至可以將它們解析爲單獨的選項,以便所有參數都是文件名(即第一個和第二個參數不會有不同的處理)。

#!/bin/sh 
# Usage: renameFiles prefix extension {filenames} 

# First argument is the new file name prefix 

PREFIX=$1 
shift 

# Second argument is the new file name extension 

EXT=$1 
shift 

# Calculate the maximum width of the number in the new file names 

TMP=`echo $# | wc -c` 
NUMBER_OF_DIGITS=`expr $TMP - 1` # Because TMP also counts the newline character 

# Process all the remaining arguments as file names 

COUNT=1 
for FILE in "[email protected]" 
do 
    NEW_NAME=`printf "${PREFIX}%0${NUMBER_OF_DIGITS}d.${EXT}" $COUNT` 

    # If you wish, prompt the user here 

    mv "$FILE" "$NEW_NAME" 
    COUNT=`expr $COUNT + 1` 
done 

#EOF 

周圍的$ @和第一個參數MV命令的雙引號需要的腳本工作,如果任何參數文件名包含空格。如果前綴和/或擴展名包含空格,則腳本需要使用圍繞命令mv命令的第二個參數的雙引號。

+0

我知道「gpRenameWithZero歌* test_ mp3」將無法正常工作。但是,通過espacing *它可以工作:「gpRenameWithZero song \\ * test_ mp3」。當您使用\\ * – user328211 2014-08-27 15:56:26

+0

替換參數中的空格時,它也適用。如果通配符被轉義,則它在第一次傳入腳本時不會擴展,但在$ 1被替換並在腳本內部展開後展開。不過,這不是一個好的方法,因爲故意傳遞逃脫通配符並不是傳統的,也不是必需的。 – Hoylen 2014-09-07 12:39:50