一連のファイルの拡張子の名前を変更するにはどうすればよいですか?


480

ディレクトリには、たくさんの*.htmlファイルがあります。すべての名前を変更したい*.txt

どうやってやるの?私はbashシェルを使用しています。

回答:


382

より良い解決策(外部呼び出しではなくbash機能のみ)については、他の回答の1つを参照してください。


以下は、システムにrenameプログラムをインストールすることを要求し、要求しません(ほとんどの場合、システムでこれを実行します)。

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

編集:コメントで指摘されているように、これは適切な引用符なしでスペースが含まれているファイル名に対しては機能しません(現在上記で追加されています)。ファイル名にスペースが含まれていないことがわかっている自分のファイルのみで作業する場合は機能しますが、後で再利用される可能性があるものを作成する場合は、適切な引用をスキップしないでください。


47
代替、ベース名なし、引用符付き:mv "$ {file}" "$ {file
/%。html

7
もちろん、ファイルがすべて現在のディレクトリにある場合にのみ有効です。これは、ベース名がパス名の部分を取り除くためです。ただ「注意」!
ジョナサンレフラー、

6
このソリューションは、低速であるだけでなく、スペースが含まれているファイル名でも機能しないため、不適切です。常にbashスクリプトで適切な引用を行う必要があります。mv "$ file" "$(basename" $ file ".html)"。txtの方がはるかに優れています。それでも、mv "$ files" "$ {files%.html} .txt"の方がはるかに優れています。
バラージュPozsár

8
Windowsで行う操作ren *.a *.b
Muhammad

2
少なくとも、$()レガシーバックティック構文の代わりにPOSIX指定の構文を使用してください。読みやすさが向上し、バックスラッシュでエスケープして、コマンド置換内でリテラルにする必要がある文字がある場合の構文の曖昧さが大幅に軽減されます。
チャールズダフィー2017

669

bashを使用する場合、sed、basename、rename、exprなどの外部コマンドは必要ありません。

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

12
また、使用できるファイル拡張子がわからない場合は、拡張子のないファイル"${file%.*}.txt"では危険な場合があります。
ジェス

1
私のようにこれを機能させるのに問題がある人には注意してください:$中括弧の中にないことに注意してください!
doug65536 2014

5
私はこの答えを永久にお気に入り/ブックマークする方法が必要です。正確な構文を覚えていないので、最終的には
ググっ

7
@danipパーセント記号の括弧内構造は、文字を末尾から取り除きます。最初から文字を取り除くブラケット内ハッシュ構造もあります。確認してください:tldp.org/LDP/abs/html/parameter-substitution.html#PSUB2

4
別のスタック交換の答え(私は見つけることができません!)がこれを提案しましたが、--「演算子」も使用しています:mv-"$ file" "$ {file%.html} .txt"この演算子は、次で始まるファイル名を防ぎます引数としてmvによって解析される「-」。
rcreswick

191
rename 's/\.html$/\.txt/' *.html

まさにあなたが望むことをします。


あなたが提案するようにbashでリテラルの正規表現を使用できないと思います-どのシェルを使用していますか?
DaveR 2009

1
私はMac端末を使用しています
bmw0128

Ubuntuでのrenameのバージョンのmanページは次のとおり
Amber

renameは、一部のシステムではコマンドです。私はその仕事をするPerlスクリプト(もともとは最初のキャメルの本から)を持っています。ほぼ同じ仕事をする同じ名前のGNUプログラムもあります。私のMacにはシステム提供の 'rename'コマンドがないか、またはPATH(中程度に包括的)にありません。
ジョナサンレフラー、

Homebrewには名前変更式があります。
revprez

112

これはOSXで.txtから.txt_bakまで機能しました

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

4
Linuxでも問題なく動作します。
Diziet 2015年

それはポイントの外ですが、あなたから行くためには連結.txtする.txt_bak必要があります_bak;)
corwin.amber

3
これは再帰的に名前を変更するのに
適しています

すごい!(Ubuntu 16.04の下)私の実際の使用例、すべての名前.scss.sass(インプレース変換後...)に変更:find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke

2
これは+6000ファイルで機能し、名前の変更は「引数リストが長すぎました」と報告されました
Tony Cronin

94

あなたが使いたいrename

rename -S .html .txt *.html

これはまさにあなたが望むことを行います-それは一致するすべてのファイルの拡張子をから.htmlに変更し.txtます*.html

注:Greg Hewgillは、これはbash組み込みではないことを正しく指摘しています。とは別のLinuxコマンドです。Linuxで何かが必要な場合、これは問題なく動作します。もっとクロスプラットフォームが必要な場合は、他の答えの1つを見てください。


7
これは良い解決策ですが、renameプログラムは関連してbashおらず、すべてのプラットフォームで利用できるわけでもありません。Linuxでしか見たことがない。
グレッグヒューギル

15
"$ rename .html .txt * .html"は...(eval 1)行1の "。"の近くで構文エラーになります。
アンバー

8
正しい構文は次のとおりであるrename -S .html .text *.htmlところ-Sの略--subst-all
マレクSebera

8
brew install rename
Nick

4
@GregHewgillの名前変更は、HomeBrewを搭載したMac OSで利用可能
CodeBrauer


15

Ubuntuユーザーの場合:

rename 's/\.html$/\.txt/' *.html

これは再帰的ではありませんが、Ubuntu 14.04ではうまくいきました。
Max Wallace

9

これは、OSXとLinuxで動作する、私が見つけた最も洗練されたソリューションです。gitでもうまく動作します。

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

とgit:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;


8

次に、renameコマンドの例を示します。

rename -n s/\.htm$/\.html/’ *.htm

-nは、テストの実行であり、実際にはファイルを変更しないことを意味します。-nを削除すると名前が変更されるファイルのリストが表示されます。上記の場合、現在のディレクトリにあるすべてのファイルをファイル拡張子.htmから.htmlに変換します。

上記のテスト実行の出力に問題がなければ、最終バージョンを実行できます。

rename -v s/\.htm$/\.html/’ *.htm

-vはオプションですが、以下のサンプル出力に示すように、renameコマンドによって行われた変更の唯一のレコードであるため、これを含めることをお勧めします。

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

真ん中のトリッキーな部分は、正規表現によるPerlの置換です。

rename -v s/\.htm$/\.html/’ *.htm

6

この質問は明示的にBashについて言及していますが、たまたまZSHを利用できるようにする場合は、非常に簡単です。

zmv '(*).*' '$1.txt'

取得したらzsh: command not found: zmv、単に実行します:

autoload -U zmv

そして、もう一度やり直してください。

zmvに関するヒントを提供してくれた元の記事に感謝します。


4

他の誰かのWebサイトをクロールした後、サブディレクトリのツリー全体で、.html拡張子のない何千ものファイルができました。

既に.html拡張子が付いているファイル(ほとんどのファイルにはまったく何もない)を除いて、すべての名前を一度に変更するには、これでうまくいきました。

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

OPの場合は、*。txtファイルの名前のみを変更するように、少し変更する場合があります。

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

壊れた(ハンマータイム!):

-iname * .txt-
既に.txtで終わるファイルのみを考慮することを意味します

mv -iv "{}。{txt、html}"- findがファイル名として{}を渡すと、$ {filename%。*}はベース名を抽出せずにmvへのパラメーターを形成します。bashは{txt、html}を取得して2つのパラメーターとして書き換え、最終的なコマンドを次のように実行します。mv -iv "filename.txt" "filename.html"

ただし、修正が必要:ファイル名のスペースの扱い


4

このコマンドはmmv、ファイルの膨大な数(秒で数万人)に非常に効率的にこの作業を行うようです。たとえば、すべての.xmlファイルの名前をファイルに変更.htmlするには、次のようにします。

mmv ";*.xml" "#1#2.html"

これ;はパスに*一致し、はファイル名に一致します。これらは、置換名として#1および#2で参照されます。

execまたはパイプに基づく応答が遅すぎるか、非常に多数のファイルで失敗しました。



3

パーティーに少し遅れました。あなたはxargsでそれを行うことができます:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

または、すべてのファイルがいくつかのフォルダにある場合

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

3
いいえ、解析しませんls。このコマンドはばかげています:グロブをls直接使用するのではなく、でグロブを無意味に使用します。これは、スペース、引用符、および(引用符がないため)グロブ文字を含むファイル名で壊れます。
gniourf_gniourf 2016年

ちなみに、あなたのリンクされた記事には、新しいLSが「ターミナルに出力された場合、ファイルを正しく「シェルエスケープ」することを示す更新されたメモが含まれています。あなたの主張は、それでもなお良い経験則です。
Katastic Voyage 2018

3

これは、一度に複数の拡張機能を変更するのに適した方法です。

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

注:拡張サイズが同じになるように注意してください(???)


2

ナイス&シンプル!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;

2

PERLを使用したい場合は、PERLの作成者であるLarry Wallによって最初に記述された短いPERLスクリプトがあり、ここで意図したとおりに動作します: tips.webdesign10.com/files/rename.pl.txt

あなたの例では、次のことがうまくいくはずです:

rename.pl 's/html/txt/' *.html

2
この質問はすでに回答され、かなり前に受け入れられており、あなたの回答がすでに述べられている以上のものをもたらすとは思われません。
ChristopheLec

1
Larry Wallスクリプト(Robin Barkerにより修正)であったため、+ 1。最後に利用可能なURLはこれです:tips.webdesign10.com/files/rename.pl.txt
loretoparisi

1

以前に提案されたものと同様に、これは私がそれをした方法です:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

私は最初に検証しました

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;

1

1行、ループなし:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

例:

$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt

+1は、既存の拡張子の正確な一致に依存しないbashのみの方法を示します。これは、3文字または4文字以上の任意の入力拡張で機能します
CiprianTomoiagăFeb

0

残念ながら、移植可能にするのは簡単ではありません。おそらく少しexprの魔法が必要です。

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

満足したら、エコーを削除します。

編集: basenameこの特定のケースではおそらく少し読みやすくなりますexprが、一般的にはより柔軟です。


これは質問に対する最良の答えではないかもしれませんが、それは私のためでした!ファイル名だけでなく、文字列でパス全体の名前のみを変更する方法が必要でした。投稿ありがとうございます!
ドーナツ

0

これは私が.edgeファイルの名前を変更するために使用したものです.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

魅力のように機能します。


0

また、Bashで関数を作成し、関数に追加して、.bashrc必要な場所で使用することもできます。

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

使用法:

change-ext css scss

関数内のコードのソース:https : //stackoverflow.com/a/1224786/6732111


0

他のパッケージなしで現在のディレクトリとサブディレクトリの下にあるすべてのファイルのファイル拡張子を変更します(シェルスクリプトのみを使用):

  1. rename.sh次のコードを使用して、現在のディレクトリの下にシェルスクリプトを作成します。

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
  2. それを実行し./rename.sh .old .newます。

    例えば。 ./rename.sh .html .txt

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