次のファイルのリストを検討してください。
$ touch index-{1,2,3,4,5,6,7,8,9}.txt
変えたいなら下にだから彼らは最初から始まります。比較的簡単:
$ rename --verbose 's/^index-([1-9])\.txt$/$1/; $_="index-" . ($_ - 1) . ".txt"' index-*.txt
man bash
これは、指定されたglobがアルファベット順にソートされ、次のように名前が変更されるために機能しますindex-1.txt
。index-0.txt
今後index-2.txt
に名前が変更されましたindex-1.txt
。
変更しようとすると失敗します。戻る、または番号が次の場合異なる長さ:
$ touch index-{10,11}.txt
$ rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' index-*.txt
index-10.txt not renamed: index-11.txt already exists
index-11.txt renamed as index-12.txt
index-1.txt not renamed: index-2.txt already exists
可能な長期修正:
rename
競合するオプションが発生しなくなるまで作業順序を再指定してください。rename
まず、ファイルを一時ディレクトリに移動してから新しい名前に戻すオプションです。rename
最初のステップでは、元の名前や新しい名前と競合しない一意の名前を使用して2つのステップにファイル名を変更するオプションです。- 自然なアライメントをする方法+裏返すBash グローバル変数。
この問題を解決する簡単な方法はありますか?
ベストアンサー1
一連の名前変更がどの順序で行われるべきかを決定するための一般的な解決策を見つけるのに役立つかもしれないUnixには、よく知られていない標準コマンドがあります。tsort
次のファイルに実行する名前変更のリストがあるとしますrenames.txt
(実演のために、その名前にスペースが含まれていないとします)。
d a
e f
b e
a c
d
名前が変更されるため、まず名前を変更する必要があるa
という意味です。したがって、ファイル名を変更する必要がある順序とは逆の部分ソート順序があります。a
d
tsort
ソート順の部分リストからソート順全体を推測するツールです。ループがあるとエラーが返されるため、解決策がない状況を検出するのに役立ちます。その入力を適用すると、tsort
次のようになります。
b
d
e
a
f
c
後に名前を変更するb
必要があることがわかります。私達は利用できますd
e
牛に似た一種の栄養 tac
(一部のシステムでも利用可能tail -r
)順序を逆にするには:
c
f
a
e
d
b
そして、名前変更リストに追加してください。
tsort renames.txt | tac | awk '
NR==FNR {
ren[$1] = $2
next
}
$1 in ren {
print "mv -i --", $1, ren[$1]
}' renames.txt -
これは私たちに以下を提供します。
mv -i -- a c
mv -i -- e f
mv -i -- d a
mv -i -- b e
その後、パイプラインを介して実行できますsh
。
ただし、上記のコードはループを検出するために上記の終了状態を確認しておらず、tsort
ファイル名に特殊なシェル文字を含めないでください。
これ堅牢性読者のための練習として残しました;-)