フォルダー内のファイルの名前を連番に変更する


230

ディレクトリ内のファイルの名前を連番に変更したい。ファイルの作成日に基づく。

sadf.jpgto 0001.jpgwrjr3.jpgto 0002.jpgなどの場合、ファイルの合計量に応じて先行ゼロの数(不要な場合は追加のゼロは不要)。


私はstackoverflow.com/questions/880467/…を見てきましたが、それを動作させることができません。
Gnutt

1
Linux / Unixは作成日を保存しません。
追って通知があるまで一時停止。

1
ls -1tr | rename -v 's /.*/ our $ i; if(!$ i){$ i = 1;} sprintf( "%04d.jpg"、$ i ++)/ e'
maXp

回答:


313

ループ、、letおよびprintfパディングに使用してみてください:

a=1
for i in *.jpg; do
  new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
  mv -i -- "$i" "$new"
  let a=a+1
done

-iフラグを使用すると、既存のファイルが自動的に上書きされるのを防ぎます。


4
printf -v new "%04d.jpg" ${a}値を変数に入れることもできます。そして((a++))、変数をインクリメントするように働きます。また、OPが指定したものである作成日順にパディングを最小化することはありません。ただし、Linux / Unixは作成日を保存しないことに注意してください。
追って通知があるまで一時停止。

3
これを私のbash環境で機能させるには、mvを二重引用符で囲む必要があります。mv "$ {i}" "$ {new}"
ゲイリートマン

2
Cygwinでもかまいません(ただし、端末の動作は通常のUnixシェルとほとんど同じです)が、ファイル名にスペースが含まれていると問題が発生するようです。
Geesh_SO 2013

2
mv -- "$i" "$new"ダッシュで始まるソースファイル名を正しく処理するために使用することもおそらく望ましいでしょう。そのままでは、mvこのようなファイル名をフラグのコレクションとして解析しようとします。
Charles Duffy

2
一目で約800個のファイルを失ってしまいました。私-iは答えに含まれるべきだと思いますし、それに応じてメモを書き直すべきです。より安全になります。:(
KrIsHnA 2017

269

一行の美しさ:

ls -v | cat -n | while read n f; do mv -n "$f" "$n.ext"; done 

あなたは変更することができ.ext.png.jpgなど、


4
凡例:)、私はこれをWindowsのgit shellで使用しましたが、うまくいきます!^^。
Mr.K 2016

4
よく働く。1行の美しさ。私はls -tr getを追加して、最後に変更された時刻までにファイルを取得しました。
Ranjith Siji、2016年

32
次のようにprintfを追加ls | cat -n | while read n f; do mv "$f" `printf "%04d.extension" $n`; doneします:ゼロ詰めの数値を使用するには
Seweryn Niemiec '23

8
警告:-n誤ってファイルを上書きしないように、mvコマンドに追加することをお勧めします。これを難しい方法で発見しました!
Ian Danforth 2017年

4
この回答などのコメントから、一緒にいくつかの素晴らしいアイデアを置く: ls -1prt | grep -v "/$" | cat -n | while read n f; do mv -n "${f}" "$(printf "%04d" $n).${f#*.}"; done 結果:(1)は、修正のために、後で索引を持つ以降のファイルを並べ替えます。(2)ディレクトリを無視します-再帰的ではありません。(3)インデックスを埋め込む。(4)元の拡張子を維持します。
ホルヘ

63

私はそのシンプルさのためにガウテのソリューションが好きですが、重要な欠点があります。何千ものファイルで実行すると、「引数リストが長すぎます」というメッセージ(これについてはさらに詳しく)が表示される可能性があります。次に、スクリプトが非常に遅くなる可能性があります。私の場合、約36.000のファイルで実行すると、スクリプトは約6000移動しました。1秒あたり1つのアイテム!なぜそうなるのかはよくわかりませんが、同僚からのルールはfindあなたの友達です」でした。

find -name '*.jpg' | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command

アイテムをカウントしてコマンドをビルドするために、gawkが使用されました。ただし、主な違いに注意してください。デフォルトでfindは、現在のディレクトリとそのサブディレクトリ内のファイルを検索するため、必要に応じて、現在のディレクトリのみを検索するように制限しman findてください(方法の確認に使用)。


7
NR短いコマンドで行番号を使用するように変更しました。gawk '{ printf "mv %s %04d.jpg\n", $0, NR }'
Apiwat Chantawibul

12
ここに大きなセキュリティの脆弱性があります。という名前のファイルがあるかどうかを考えます$(rm -rf /).jpg
Charles Duffy、2014

それをチャールズに指摘してくれてありがとう。安全な解決策を提案できますか?
beibei2 2014

2
ファイル名にスペースが含まれている場合は壊れます。ソースファイル名は引用符で囲みます。printf "mv \"%s \ "%04d.jpg \ n"、$ 0、a ++
バスキン

1
forループは、厳密に言えば、ファイルごとに1秒を取っていません。ファイルシステムから36,000のファイル名をフェッチしてから、それらを適度にすばやくループするのには長い時間がかかります。多くのファイルシステムでは、実行する正確なコマンドに関係なく、大きなディレクトリに関する問題があります。しかし、通常、一致するファイルのリストfindをフェッチしてソートする必要があるため、シェルワイルドカードよりも高速になります。
Tripleee

30

「rename」コマンドを使用

rename -N 0001 -X 's/.*/$N/' *.jpg

または

rename -N 0001 's/.*/$N.jpg/' *.jpg

32
rename(Linux Mint 13)には-Nオプションがありません。
ルークH

私はちょうど私がそれを聞いたことがないrenameコマンドの言及、のためにupvoteすることができます
user907860

8
-Nオプションを指定した名前変更コマンドをどこで取得するのか知りたいです。私のUbuntu 14.04にはそれがありません。
ステファンヘニングセン2015

1
rename命令は大好きですが、知りませんでした-N!ありがとう!
Dan Lecocq 2017

1
として知られてrenameいる少なくとも3つの異なるツールがあります。@Bostrotによって投稿されたリンクは、さらに別の名前変更ツールであり、@ RomanRhrnNesterovがそれを使用したようです。rename¶Peder StrayとLarry Wallのすべてのユーザー(perl-renamearch linuxのパッケージrenameとdebian / ubuntuのパッケージ):$N自分で定義できます:perl-rename '$N=sprintf("%04d",++$N); s/.*/$N.jpg/' *.jpg
Socowi

30

OSXでPeroのソリューションを使用するには、いくつかの変更が必要です。私が使用した:

find . -name '*.jpg' \
| awk 'BEGIN{ a=0 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' \
| bash

注:バックスラッシュは行継続のためにあります

2015年7月20日編集:スペースを含むファイル名をサポートするために\"%s\"mvコマンド の引数を引用する@klaustopherのフィードバックを組み込みました。


3
Peroのソリューションと同様に、ここにもセキュリティの脆弱性があります。という名前のファイルがあるかどうかを考えます$(rm -rf /).jpg
Charles Duffy、2014

ありがとう、これでうまくいきます。ただし、の最初の引数を引用する必要がありますmv。ieという名前のファイルがある場合some thing.jpg、スクリプトは失敗します。これは私が使用したものである:find . -name '*.jpg' | awk 'BEGIN{ a=0 }{ printf "mv \"%s"\ wallpaper-%04d.jpg\n", $0, a++ }' | bash
klaustopher

-maxdepth 1申し訳ありませんが安全である方が良いので、おそらく現在のディレクトリのjpgでのみ作業するために使用します。
PeterPerháč16年

パイプ文字を前の行の終わりに移動する場合、バックスラッシュは必要ありません。
Tripleee

ls -1 *.jpg検索の代わりに使用できます。それ以外の場合は並べ替えられません。または、|sort|前のawkを追加します
JPT

28

元の拡張を維持し、先行ゼロを追加し、OSXでも機能する非常にシンプルなbash oneライナー:

num=0; for i in *; do mv "$i" "$(printf '%04d' $num).${i#*.}"; ((num++)); done

http://ubuntuforums.org/showthread.php?t=1355021の簡略版


まさに私が探していたもの。開始インデックスを設定できるのが好きです。
Jack Vial

2
これはファイルの元の順序を維持しないことに注意してください。
Roy Shilkrot、2018年

@RoyShilkrot» どういう意味ですか» 元の順序を維持しません «?bashおよびその他のposixシェルのグロブは、システムのロケールに従ってソートされた順序で展開されます。もちろん、これは9.ext以前11.extにソートされませんが、他のツール(などls)もソートされません。
ソコウィ

11

すべての状況で機能するには、名前にスペースが含まれるファイルに\ "を付けます

find . -name '*.jpg' | gawk 'BEGIN{ a=1 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' | bash

3
実際にはすべての状況をカバーしているわけではありません。リテラルの引用符を含むファイル名は、簡単にエスケープできます。また、単一引用符ではなく二重引用符を使用しているため、などの展開$(rm -rf /)は引き続き有効です。
Charles Duffy

11

renameがをサポートしていない場合は-N、次のようなことができます。

ls -1 -c | xargs rename -n 's/.*/our $i; sprintf("%04d.jpg", $i++)/e'

編集特定の数値で開始するには、以下の(やや醜い)コードを使用できます。123を目的の数値に置き換えるだけです。

ls -1 -c | xargs rename -n 's/.*/our $i; if(!$i) { $i=123; } sprintf("%04d.jpg", $i++)/e'

これは、ファイルを作成時刻順にリストし(最初に最新、-rlsに追加して逆ソートする)、次にこのファイルのリストを送信して名前を変更します。名前の変更では、正規表現のperlコードを使用して、カウンターをフォーマットおよびインクリメントします。

ただし、EXIF情報を含むJPEG画像を処理している場合は、 exiftool

これは、「名前の変更の例」のexiftoolドキュメントからのものです

   exiftool '-FileName<CreateDate' -d %Y%m%d_%H%M%S%%-c.%%e dir

   Rename all images in "dir" according to the "CreateDate" date and time, adding a copy number with leading '-' if the file already exists ("%-c"), and
   preserving the original file extension (%e).  Note the extra '%' necessary to escape the filename codes (%c and %e) in the date format string.

どのようにして特定の番号から開始できrenameますか?
1

6

OSXで、Homebrewからrenameスクリプトをインストールします。

brew install rename

それからあなたはそれを本当に途方もなく簡単に行うことができます:

rename -e 's/.*/$N.jpg/' *.jpg

または、素敵な接頭辞を追加するには:

rename -e 's/.*/photo-$N.jpg/' *.jpg

3
これはすばらしいスクリプトであり、Perlにのみ依存します。brewはMacでのみ機能しますが、github(github.com/ap/rename)から取得してLinuxまたはWindowsで使用できます。
Tim Danner

3
これは私にはうまくいきません。私が得たGlobal symbol "$N" requires explicit package name (did you forget to declare "my $N"?) at (user-supplied code).
アンソニー・チョン

Macユーザーとして、@ TimDannerによってリンクされた名前変更アプリケーションは非常に移植性が高く、Zipアーカイブをダウンロードして、bashプロファイルのパスが表示されるように設定されているディレクトリに名前変更ユーティリティをドロップするだけで簡単に報告できる、それは箱から出してすぐに動作します。これがMacPortsで利用できないことに驚いています。Rename(2)のBSDマンページがあるほど奇妙ですが、renameを実行すると、コマンドが存在しないと表示されます。図を行きます。
adamlogan

2

コマンドに従って、すべてのファイルの名前をシーケンスに変更し、小文字の拡張子を付けます。

rename --counter-format 000001 --lower-case --keep-extension --expr='$_ = "$N" if @EXT' *

1

同様の問題があり、そのためシェルスクリプトを作成しました。誰かに役立つと思うので、良い回答がたくさん投稿されていても、投稿することにしました。自由に改善してください!

列挙する

@Gnutt次のように入力すると、必要な動作を実現できます。

./numerate.sh -d <path to directory> -o modtime -L 4 -b <startnumber> -r

このオプションを-r省略した場合、リーマのシミュレーションのみが行われます(テストに役立つはずです)。

オプションLは、ターゲット番号(先行ゼロで埋められます)の長さを示します-p <prefix> -s <suffix>。オプションで接頭辞/接尾辞を追加することもできます。

誰かが番号付けされる前にファイルを数値順に並べ替えたい場合は、-o modtimeオプションを削除してください。



1

これらのファイルが、作成順にリストされたディレクトリにあり、最初が最も古いと仮定します。

a.jpg
b.JPG
c.jpeg
d.tar.gz
e

次にls -1cr、上記のリストを正確に出力します。次に使用できますrename

ls -1cr | xargs rename -n 's/^[^\.]*(\..*)?$/our $i; sprintf("%03d$1", $i++)/e'

出力する

rename(a.jpg, 000.jpg)
rename(b.JPG, 001.JPG)
rename(c.jpeg, 002.jpeg)
rename(d.tar.gz, 003.tar.gz)
Use of uninitialized value $1 in concatenation (.) or string at (eval 4) line 1.
rename(e, 004)

拡張子のないファイルに対しては、「初期化されていない値の使用[…]」という警告が表示されます。無視してかまいません。

コマンドから削除-nして、rename実際に名前変更を適用します。

この回答は、2014年4月のルークの回答に触発されました。ファイルの合計量に応じて先行ゼロの数を設定するというGnuttの要件は無視されます。


これは私にとってここで最も有用な答えでした。主に、実行する前にopをドライランしたかったためとls -1tU、作成時間に変更することで順序を調整できるためです。renameインストールも必要でしたが、私は持っていませんでした。
アントニー

1

ここでも、ほとんど変更せずにPeroのソリューションを使用します。 findます。これは、アイテムがディレクトリエントリ内に格納されている順序でディレクトリツリーを走査するためです。これは、(ほとんどの場合)同じマシン上で実行間で一貫しており、削除されていない場合は基本的に「ファイル/ディレクトリの作成順序」になります。

ただし、場合によっては、この例で使用される名前などの論理的な順序を取得する必要があります。

find -name '*.jpg' | sort -n | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command 

3
これは使用しないでください。このようにbashにリダイレクトすることは、大きなセキュリティリスクです。ファイル名の1つが次の形式の場合はどうなりますblahblah; rm -r * blahblah.jpgか?
xhienne

1

時間でソートされ、jpg、先行ゼロ、およびベース名に限定されます(必要な場合に備えて)。

ls -t *.jpg | cat -n |                                           \
while read n f; do mv "$f" "$(printf thumb_%04d.jpg $n)"; done

(すべて1行で、なし\


物事の壮大な計画では、このページの多くの答えは恐ろしいので、多分これは特に反対票に値しないでしょう。でもls、スクリプトで使用するものは何でも賛成投票するのをためらっています。
Tripleee

おそらく壊れやすいものの、私が持っていた特定のユースケースではうまくいったので、私はこの答えを否定的な面から保存します。
Ville

1
ls -1tr | rename -vn 's/.*/our $i;if(!$i){$i=1;} sprintf("%04d.jpg", $i++)/e'

rename -vn-オフテストモードでnを削除

{$ i = 1;} -コントロールの開始番号

"%04d.jpg" -カウント04を制御し、出力拡張子.jpgを設定します


この回答は、ネイティブの名前変更のみを使用しているため、賛成です。私の使用例は、ファイルの最初の2桁を01から始まる番号に置き換えることでした:rename -v -n 's/../our $i;if(!$i){$i=1;} sprintf("%02d", $i++)/e' *
18.

1

私にとって、この答えの組み合わせは完璧に機能しました:

ls -v | gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | bash
  • ls -v 1 10 9を正しい順序で並べるのに役立ちます:1 9 10順序、jpg JPG jpegでのファイル名拡張子の問題を回避
  • gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }'4文字と先行ゼロで番号を付け直します。mvを回避することで、誤って同じ番号を使用して、すでにあるものを誤って上書きしようとはしません。
  • bash 実行する

@xhienneの発言に注意してください。未知のコンテンツをbashにパイプすることはセキュリティ上のリスクです。しかし、スキャンした写真を使用していたため、これは私には当てはまりませんでした。


0

lsも使用できます

ls *.JPG| awk 'BEGIN{ a=0 }{ printf "mv %s gopro_%04d.jpg\n", $0, a++ }' | bash

5
mywiki.wooledge.org/ParsingLsと、同様に壊れた他のソリューションのセキュリティ脆弱性の説明もご覧ください。
Charles Duffy

1
これは使用しないでください。このようにbashにリダイレクトすることは、大きなセキュリティリスクです。ファイル名の1つが次の形式の場合はどうなりますblahblah; rm -r * blahblah.JPGか?
xhienne

0

他のソリューションの大半は、すでに番号として指定されている既存のファイルを上書きします。これは、スクリプトを実行してファイルを追加し、スクリプトを再度実行する場合に特に問題になります。

このスクリプトは、最初に既存の数値ファイルの名前を変更します。

#!/usr/bin/perl

use strict;
use warnings;

use File::Temp qw/tempfile/;

my $dir = $ARGV[0]
    or die "Please specify directory as first argument";

opendir(my $dh, $dir) or die "can't opendir $dir: $!";

# First rename any files that are already numeric
while (my @files = grep { /^[0-9]+(\..*)?$/ } readdir($dh))
{
    for my $old (@files) {
        my $ext = $old =~ /(\.[^.]+)$/ ? $1 : '';
        my ($fh, $new) = tempfile(DIR => $dir, SUFFIX => $ext);
        close $fh;
        rename "$dir/$old", $new;
    }
}

rewinddir $dh;
my $i;
while (my $file = readdir($dh))
{
    next if $file =~ /\A\.\.?\z/;
    my $ext = $file =~ /(\.[^.]+)$/ ? $1 : '';
    rename "$dir/$file", sprintf("%s/%04d%s", $dir, ++$i, $ext); 
}

0

このワンライナーは、現在のディレクトリ内のすべてのファイルを一覧表示し、作成タイムスタンプで逆の順序で並べ替え(最も古いファイルが先頭にあることを意味します)、ファイルの数に応じて末尾のゼロで自動的に名前を変更します。ファイル拡張子は保持されます。

私は通常、携帯電話の写真や映画用のフォルダーを1つだけ持っています。このコマンドを適用すると、私の写真とムービーの準備が整い、テレビまたはアーカイブで正しい順序でスライドショーを表示できるようになります。

ファイル名の衝突があると、ファイルが失われることに注意してください。そのため、最初に、何か変な名前に変更してtemp001.jpgから、最終的なファイル名に実行してください。

DIGITS=$(ls | wc -l | xargs | wc -c | xargs); ls -tcr | cat -n | while read n f; do mv "$f" "$(printf "%0${DIGITS}d" $n).${f##*.}"; done

1
ls1回ではなく2回実行することは、このようにしない方がよいように見えますが、これについては詳しく調べていません。
Tripleee

1.意図的にワンライナーを提案した場合、なぜ後で変更するのですか?私のような多くのユーザーは、タスクを完了するためにワンライナーをコピーアンドペーストすることを好みます。行ごとにコピーすることを好む他の人のために、このスレッドには他の答えがあります。2.元の質問は「ファイルの総量に応じた先行ゼロの数」でしたが、これは最初のlsで行われるため、2つ必要です。3.このようなコマンドはワンショットであり、スクリプトに含めることを意図していないため、人々がワンライナーを好む理由があります
Flavio Aiello

1
申し訳ありませんが、それが重要だと思っていました。私にとって、コードを読み取ることができるということは、コードを1行としてコピー/ペーストする能力に大きく勝ります。Bashが複数行にまたがる貼り付けで問題が発生するような環境は見つかりませんでしたが、何かを見落としている可能性があります。
tripleee

0

ここに私のために働いたものがあります。renameコマンド
を使用して、名前にスペースが含まれているファイルがある場合、mvコマンドがスペースと実際のファイルを混同しないようにしています。

ここで、すべてのjpgファイルについて、ファイル名のスペース、「」を「_」に置き換えました
#!/ bin / bash
名前の変更 'y / / _ /' * jpg#スペースを_で置き換える
x = 0とします。
* .jpg;のiの場合
    x =(x + 1)とする
    mv $ i $ x.jpg
終わった

Linuxに名前変更をインストール(ubuntu)、「sudo apt install rename」
rishang bhavsar

0

現在、名前を変更するために複数のファイルを選択した後のオプションがあります(私はthunarファイルマネージャーで見ました)。

  1. 複数のファイルを選択
  2. チェックオプション
  3. 名前の変更を選択

プロンプトはその特定のディレクトリ内のすべてのファイルに付属しています。カテゴリセクションで確認してください


-1

このスクリプトは、Mac OS bashで作成日順にファイルをソートします。私はそれを使ってビデオの名前を一括変更します。拡張子と名前の最初の部分を変更するだけです。

ls -trU *.mp4| awk 'BEGIN{ a=0 }{ printf "mv %s lecture_%03d.mp4\n", $0, a++ }' | bash

1
これは使用しないでください。このようにbashにリダイレクトすることは、大きなセキュリティリスクです。ファイル名の1つが次の形式の場合はどうなりますblahblah; rm -r * blahblah.mp4か?
xhienne

-1

ここで、「rename」コマンドを使用した別のソリューション:

find -name 'access.log.*.gz' | sort -Vr | rename 's/(\d+)/$1+1/ge'

先頭のゼロを復元するには:rename 's/(\d+)/sprintf("%04d",$1)+1/ge'
Camille Goudeseune 2015年

DSC_3451.JPG、DSC_3452.JPGなどの名前のファイルがあるフォルダーの場合、期待どおりに機能しません。find-name '* .JPG' | sort -Vr | 名前変更 's /(\ d +)/ $ 1 + 1 / ge'は何も変更しません
Tiberiu C. '29

-2

ペロの答えは私をここにもたらしました:)

画像ビューアが時間順に画像を表示しなかったので、時間に関連してファイルの名前を変更したいと思いました。

ls -tr *.jpg | # list jpegs relative to time
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command

2
これは使用しないでください。このようにbashにリダイレクトすることは、大きなセキュリティリスクです。ファイル名の1つが次の形式の場合はどうなりますblahblah; rm -r * blahblah.jpgか?極端な例です。
xhienne 2017年


-3

1つのフォルダにある6000のファイルの番号を変更するには、ACDseeプログラムの「名前の変更」オプションを使用できます。

プレフィックスを定義するには、次の形式を使用します。 ####"*"

次に、開始番号を設定して[名前の変更]を押すと、プログラムはすべての6000ファイルの名前を連番で変更します。


1
OPは、Unix Bourne Shellで一連のコマンドを要求します。あなたは、Windows環境でのみ動作する商用製品を提案しています。
xhienne 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.