Bashスクリプトを使用して複数のファイルの名前を変更する


27

Bashスクリプトを使用して、同じディレクトリ内の複数のファイルの名前を変更したい。ファイルの名前は次のとおりです。

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

次の形式に名前を変更したい:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

私はrenameコマンドについて読んでいて、このようにしようとしましたが、何もしません。構文について質問があると思います。次に、次のようにmvコマンドを使用してループを作成できることを読みました。

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"
done

しかし、ファイルの名前を変更することはできません。何が間違っていますか?



2
パラメーター展開置換式の右側にパターン式を含めることはできません。それ*がどこにあると期待していましたか?
小次郎

@Kiwyその質問は、ファイル名の一部を削除することです。エルゴ、非常に疑わしい複製。
CVn 14年

2
次回、あなたがしたいファイル名の変更について説明してください(違いや類似点を見る前に、これをかなり見なくてはなりませんでした)。例は良いですが、説明例はさらに良いです。
CVn

回答:


42

最初に名前の変更を検討するのが正しかった。あなたが正規表現に慣れていない場合、構文は少し奇妙ですが、あなたが何をしているのかを知ったら、それは断然最短/最短のルートです:

rename 's/\d{4}/2503/' file*

これは、最初の4つの番号と単に一致し、指定した番号と交換します。

そして、ファイル名を使用したテストハーネス(-vn冗長であるが何もしないことを意味します):

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p

8
これはDebianおよび派生物(Ubuntu、Mint、…)でのPerlの名前変更であることに注意してください。他のLinuxディストリビューションでrenameは、まったく異なるファイル名変更ツールです(Debianとして出荷されますrename.ul)。
ジル 'SO-悪であるのをやめる' 14年

このようなツールが配布不足である場合は、@ Michael Campbellの回答をご覧ください。renamedebianが行ったように、すべての分配はデフォルトを置き換えると思います。
アステリー

25

これでうまくいくはずです:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

4番目と12番目の文字の間の文字列を「25032014」に置き換えます。


これfor f in file*; do mv $f ${f/${f:4:4}/2503}; doneも機能します。
アビナッシュラジ14年

それはすばらしい。単語置換のために通常の単語を実行したいだけであれば、sedのように機能します。例for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
エリック

1
@Eric-より明確でエレガントだと思うので、私はあなたの答えを選択肢として投稿しました。あなたも答えとしてそれを投稿したい場合-私は私のものを削除します。ありがとう!
エホセフ

なぜ二重引用符がないのですか?
ワイルドカード

「mv:ターゲット 'FILE_NAME'はディレクトリではありません」というエラーが表示されます
オーブリー

10

これは上からの@Ericの答えです-しかし、それはエレガントな答えなので、私はそれにもっと注意を引くために適切な答えとしてそれを再投稿しています。

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done

1
ptrn='file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p'
path=/dir
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
        ${path}/file25032014${f#2014}" 
} ; done )

これでうまくいくはずです。注-大量のmvコマンドを渡す習慣はありません-書かれているように、それは単なるエコーです。動作する前にそれを整理する必要があります。


1

ディレクトリトラバーサルを使用して、ループせずにそれを行う簡単なネイティブ方法:

find -type f | xargs -I {} mv {} {}.txt

所定の場所にあるすべてのファイルの名前が変更されます。

そして、以下の並列化の動作例:

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'

より良いソリューションを想像するのは簡単な最初のアプローチでした。あなたが働いてコマンドを使用する場合は実行します
dtrckd

find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
dtrckd

0

このようなことを頻繁に行う場合は、「rename.pl」を検索してください。これはperlスクリプトですが、perlコード(as /// expressionなど)を単純にフィードすることができ、その式またはコードに基づいて一括名前変更を行います。

http://stackoverflow.org/wiki/Rename.plには基本的なバージョン がありますが、ネット上には他のバージョンもあります。それは年齢、年齢、年齢に関係なく存在します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.