1

次のスクリプトを実行して、現在のフォルダー内のすべての .jpg ファイルの名前を変更するとうまくいく場合もありますが、名前を変更している 1 つまたは複数のファイルが削除されることがよくあります。プロセスでファイルを削除せずにファイルの名前を変更するスクリプトを作成するにはどうすればよいですか? これは、GNU bash、バージョン 3.2.48 を使用して Mac OSX 10.8 で実行されています。

これは、説明のために変更するファイル リストの例です。

元のファイル

red.jpg
blue.jpg
green.jpg

カウンターが 5 に設定されている場合、名前が変更されたファイル

file_5.jpg
file_6.jpg
file_7.jpg

代わりに、通常は 1 つまたは複数のファイルを失います

#!/bin/bash  

counter=5

for file in *.jpg; do

    echo renaming "$file" to "file_${counter}.jpg";
    mv "$file" "file_${counter}.jpg";
    let "counter+=1";

done

**更新**

ファイルを削除しているようには見えなくなりましたが、出力はまだ期待どおりではありません。例えば:

file_3.jpg
file_4.jpg

になる

file_3.jpg
file_5.jpg

カウンターが 4 に設定されている場合、期待される出力が

file_4.jpg
file_5.jpg

-

#!/bin/bash  

counter=3

for file in *.jpg; do

    if [[ -e file_${counter}.jpg ]] ; then
        echo Skipping "$file", file exists.
    else
        echo renaming "$file" to "file_${counter}.jpg"
        mv "$file" "file_${counter}.jpg"
    fi

    let "counter+=1"

done
4

5 に答える 5

10

問題は、一部のファイルがターゲット名に対応する名前をすでに持っていることです。たとえば、ファイルがある場合

file_1.jpg
file_7.jpg

で開始し、最初のステップで でcounter=7上書きfile_7.jpgしてから、名前を に変更します。file_1.jpgfile_8.jpg

クロバリングを防止するために使用mv -nしたり (サポートされている場合)、コマンドを実行する前に存在をテストしたりできます。

if [[ -e file_${counter}.jpg ]] ; then
    echo Skipping "$file", file exists.
else
    mv "$file" "file_${counter}.jpg"
fi
于 2013-08-14T14:58:11.180 に答える
2

グロブの明らかな問題に目を光らせていると思います。グロブが file_2.jpg と一致する場合、file_file_2.jpg を作成しようとします (文字通りの意味ではなく、既に処理したファイルを再処理するという意味です)。これを解決するには、最初のグロブ式が既に移動したファイルと一致しないようにする必要があります。

shopt -s extglob

i=0
for f in !(file_*).jpg ; do
    while [[ -e "file_${i}.jpg" ]] ; do
        (( i++ ))
    done

    mv -v "$f" "file_$i.jpg"
    (( i++ ))
done
于 2013-08-14T15:07:08.890 に答える
1

もう 1 つの方法は、ファイルが存在しなくなるまでカウントを続けることです。

#!/bin/bash  

counter=1
shopt -s extglob

for file in *.jpg; do
    [[ $file == ?(*/)file_+([[:digit:]]).jpg ]] && continue

    until
        newname=file_$(( counter++ )).jpg
        [[ ! -e $newname ]]
    do
        continue
    done

    echo "renaming $file to $newname.";

    mv -i "$file" "$newname" ## Remove the -i option if you think it's safe already.
done

物事を再帰的に行う場合:

#!/bin/bash  

shopt -s  extglob    
counter=1

while read file; do
    dirprefix=${file%%+([^/])

    until
        newfile=$dirprefix/file_$(( counter++ )).jpg
        [[ ! -e $newfile ]]
    do
        continue
    done

    echo "renaming $file to $newfile."

    mv -i "$file" "$newfile" ## Remove the -i option if you think it's safe already.
done < <(find -type f -name '*.jpg' -and -not -regex '^.*/file_[0-9]\+$')
于 2013-08-14T15:20:58.203 に答える