複数のファイルの名前をmvに変更して、拡張子を変更します


27

ファイルの名前を変更して拡張子を変更し、効果的に達成したい

mv *.txt *.tsv

しかし、これを行うとき、私は得る:

* .tsvはディレクトリではありません

最初の10回のGoogleヒットショーmvがこのように機能するのは少し奇妙です。


これらのファイルの名前を正確に変更する方法を説明する必要があります。
トーター

1
さて、*。gappedPeakの拡張子を持つファイルがあり、*。bedに名前を変更したいです。彼らは私が成功するために必要だった非常にシンプルだがループを完全にする必要があり、同じディレクトリ内のすべてのです
サンダーヴァン・ゼーウデル・

Googleで見つけたものは、MSDOSに適用されると思います。
tiktak

@devnullの代替ソリューションは本当に役立ちます
lucasvw

回答:


22

コマンドを発行するとき:

mv *.txt *.tsv

シェルは、bashを想定して、一致するファイル(ディレクトリを含む)があればワイルドカードを展開します。ファイルのリストは、ここでプログラムに渡されます。一致するものが見つからない場合、展開されていないバージョンが渡されます。mv

繰り返しますが、シェルはプログラムではなくパターンを展開します。


たくさんの例がおそらく最良の方法なので、ここに行きます:

例1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv

mv行で何が起こるかは、シェル*.txtが一致するファイルに展開することです。*.tsv変更されていないファイルがないため。

mvコマンドが呼び出された二つの特別な引数を持ちます

  • argc:プログラムを含む引数の数。
  • argv:最初のエントリとしてプログラムを含む引数の配列。

上記の例では:

 argc = 4
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = file2.txt
 argv[3] = *.tsv

mv最後の引数は、かどうかを確認するためにプログラムチェック*.tsv、ディレクトリです。そうではないため、ファイルを連結するように設計されていないため、プログラムは続行できません。(通常、すべてのファイルを1つに移動します。)気まぐれにディレクトリを作成することもできません。

結果として、異常終了し、エラーを報告します。

mv: target ‘*.tsv’ is not a directory

例2:

代わりに言うなら:

$ mv *1.txt *.tsv

mvコマンドがで実行されます。

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = *.tsv

もう一度、存在するmvかどうかを確認します*.tsv。ファイルfile1.txtはに移動されないため*.tsv。つまり、ファイル名が*.tsvアスタリスクとすべてに変更されます。

$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’

$ ls
file2.txt *.tsv

例3:

代わりに言った場合:

$ mkdir *.tsv
$ mv *.txt *.tsv

mvコマンドがで実行されます。

 argc = 3
 argv[0] = mv
 argv[1] = file1.txt
 argv[1] = file2.txt
 argv[2] = *.tsv

*.tsv今そこに移動されるまでのファイルが終了すると、ディレクトリです。


現在:some_command *.tsvワイルドカードを実際に保持することを意図している場合など、常に引用符で囲む必要があるコマンドを使用します。引用符を付けることにより、一致する必要がある場合にワイルドカードが展開されるのを防ぎます。例えば、言いますmkdir "*.tsv"

例4:

展開は、たとえば次の場合にさらに表示できます。

$ ls
file1.txt file2.txt

$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists

例5:

現在:このmvコマンドは、複数のファイルで機能します。ただし、2つ以上ある場合は、最後のディレクトリをターゲットディレクトリにする必要があります。(-t TARGET_DIRオプションで、少なくともGNU mvではこのオプションを使用できます。)

だからこれはOKです:

$ ls -F
b1.tsv  b2.tsv  f1.txt  f2.txt  f3.txt  foo/

$ mv *.txt *.tsv foo

ここmvで呼び出されます:

 argc = 7
 argv[0] = mv
 argv[1] = b1.tsv
 argv[2] = b2.tsv
 argv[3] = f1.txt
 argv[4] = f2.txt
 argv[5] = f3.txt
 argv[6] = foo

そして、すべてのファイルがディレクトリに配置されますfoo


リンクについて。あなたは(コメントで)1つを提供しましmvrename。さらにリンクがある場合は、共有できます。あなたが主張しているマニュアルページについても同様です。


30

これはあなたの質問に答えないことはわかっていますが、回避ループと比較してファイルの名前を変更する別の方法を探している場合は、なぜ使用しないのfindですか?このコマンドを何度も使用して、大きなディレクトリのファイル拡張子を何十万ものファイルに置き換えました。これは、POSIX準拠のシステムで動作するはずです。

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

コマンドの内訳:

  1. ' .' => 'でマークされた現在のディレクトリから始まる検索パス。'

  2. -name=>検索一致名の設定(この場合、で終わるすべてのファイル .gappedPeak

  3. -exec =>一致するたびに次のコマンドを実行します

  4. sh -c => 'exec'は、一致するたびに独立したシェル環境を作成します

  5. mv "$1" "${1%.gappedPeak}.bed"=> 現在のファイル名であるmv最初の変数($ 1で示される)から新しい名前。ここでは、部分文字列の一致と削除を行います。したがって、最初の変数$ 1を再び使用%.gappedPeakて、文字列から削除するために使用します。.bed最後には、ちょうど今ある残りの変数を、連結して、新しい作成し、ファイル名を。test#.bedtest#.bed

  6. 下線は$ 0のプレースホルダーです

  7. {}各(置き換えられている*.gappedPeakことで見つかった)、ファイル名find、コマンド、およびなり、$ 1shコマンド。

  8. \;-execコマンドの終わりを示します。';'またはを使用することもできます";"

例:

[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak

[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed

各部分の機能を説明するコマンドを実行できますか?
-user1717828

申し訳ありませんが、投稿を更新しました。お役に立てば幸いです。
-devnull

1
素晴らしいです、ありがとう!bashのガイドとご説明私はすべてを取得することができました。
user1717828

問題ない。喜んでいます。
-devnull

魔法のように機能します。複数のサブディレクトリでのfile.abc-> の別の簡単な例を次に示しblub.xyzます。find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
Mahn

9

mv *.txt *.tsv動作しません。mv一度に1つのファイルのみ名前を変更できます。説明を誤解しているか、間違っています。

mmvそして、rename一度に複数のファイルの名前を変更することができます。しかし、renamearound には2つのバージョンがあり、それぞれ異なる方法で呼び出されます。ここでそれについて多くの質問があるはずです。


1
cyberciti.biz/tips/... Googleで最初のヒットは、私はそれはとても奇妙た理由MVが井戸のthatsとして動作するべきであると言っている
サンダーヴァン・ゼーウデア・

3
@SanderVanderZeeuwあなたがそこに何を読んだかわかりません。例ではrename、ではなくを使用していmvます。
ハウケレイジング

1
申し訳ありませんが、間違ったHTMLを貼り付けました。これはudemy.com/blog/rename-a-file-in-linuxでした。
サンダー

3
@SanderVanderZeeuw恥ずかしい。これらの人々はコースを提供していますか?残念ながら、そこに連絡の可能性はありません。これが機能するかどうかを簡単に確認できます。しかし、中にmv *.txt *.tsv mv(通常は)見ていない*.txt*.tsvが、シェル拡張ファイル名。これらのワイルドカードが展開するファイルの数は「ランダム」です。これが機能する唯一の状況は、名前*.txtが(文字通り)に変更される名前のファイルがある場合です*.tsv(引用符なしでbashオプションをnullglob設定しないでください)。
ハウケレイジング

1
またはさらに悪い。一つは持っている場合は1つのという名前のファイルなどfoo.txt1という名前の既存の上書きされますファイルを...baz.tsvmv *.txt *.tsv.tsv
Runium

4

あなたが持っている場合たとえば、asd.txtqwe.txtあなたはコマンドを実行すると、ディレクトリ内のファイルmv *.txt *.tsvは、名前のディレクトリにこれらの2つのファイルを移動しようとします*.tsv。そのようなディレクトリがないため、エラーが発生します。


おかげで、これは部分的に明確になります。それでも、mvが複数で機能するはずだと主張するマニュアルページが非常に多いのは奇妙です。
サンダーヴァンデルゼーウ

2

rename(1)

renameperlの作成者であるLarry Wallによるperlスクリプトです。Perl正規表現を取り、ファイル名で動作します。

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

設置

Debian / Ubuntu

renameDebian / Ubuntu にインストールする必要がある場合は、以下を実行できます。

sudo apt install rename

0

考慮すべきもう1つのオプションは、以下を使用することです。

cp -p *.txt *.tsv
rm -f *.txt
  • 最初の行は、フラグを使用して属性を保持*.txt*.tsvながらすべてのファイルをコピーします-p
  • 2行目は、パターンを持つすべてのファイルを削除します *.txt
  • この方法では、ソースファイルとターゲットファイルの両方を一時的に保持するのに十分なディスク領域が必要です。
  • この方法はmv、ファイルが別のパーティションにない限り、実際にファイルを移動せずに単に/ directory / filenameを変更するよりも遅いです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.