
拡張子を変更するためにファイル名を変更したいと思います。効果的に完了しようとしています。
mv *.txt *.tsv
しかし、これを行うと、次のような結果が得られます。
*.tsv はディレクトリではありません。
mv
最初の10回のGoogleクリックマークがこのように機能することが少し奇妙だと思います。
答え1
これがあなたの質問に対する答えではないことを知っていますが、回避策ループではなくファイル名を変更する別の方法を探している場合はfind
?私は何十万ものファイルを含む大規模ディレクトリのファイル拡張子を置き換えるためにこのコマンドを複数回使用しました。これはすべてのPOSIX互換システムで機能します。
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
コマンド分析:
'
.
'=>' で示される現在のディレクトリから始まる検索パス。 '
-name
=>照会一致名の設定(この場合で終わるすべてのファイル.gappedPeak
)
-exec
=> 各ゲームで次のコマンドを実行します。
sh -c
=> 'exec'はゲームごとに別々のシェル環境を作成します。
mv "$1" "${1%.gappedPeak}.bed"
=>mv
最初の変数(次のように表現されます)1)(現在のファイル名)が新しい名前に変更されます。ここでは部分文字列のマッチングを実行して削除するので、最初のvarを再取得します。1文字列から削除するために使用されます%
。.gappedPeak
最後の.bed
変数は、残りの変数(以下の例では、)を連結して新しいファイル名を作成します。testNumber
.bed
testNumber.bed
下線はプレースホルダです。$0
{}
は、コマンドで見つかった*.gappedPeak
各()ファイル名に置き換えfind
られます。1sh
コマンドに。
\;
コマンドの終わりを表示します-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
答え2
この答えは、拡張を変更するのには役に立ちませんが、コマンドが期待どおりに実行されない理由を理解するのに役立ちます。
コマンドを実行すると、次のようになります。
mv *.txt *.tsv
シェル、bashを仮定しましょう。拡大するワイルドカードもし一致するファイル(ディレクトリを含む)があります。ファイルのリストはここからプログラムに渡されますmv
。一致するものがない場合、拡張されていないバージョンが渡されます。
再:シェルプログラムではなく拡張モードです。
多くの例は、おそらくこれがうまくいかない理由を理解するための最良の方法です。それでは始めましょう。
例1:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
mv
今オンラインで起こっていることはシェル*.txt
一致するファイルに展開します。変更されていないファイルがないためです*.tsv
。
コマンドmv
が呼び出されます。2つの特別なパラメータがあります。:
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
。何もなかったので、ファイルは.iefile1.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では、このオプションを使用することを選択できます。)
だからこれは大丈夫です:
$ 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
。
あなたのリンクは。あなたはmv
まったく言及されていないものを(コメントに)提供しましたrename
。しかし、あなたの主張を表現する共有できるリンクやマニュアルページはありますか?
答え3
mv *.txt *.tsv
動作しません。mv
一度に1つのファイルのみ名前を変更できます。あなたはこれらの説明を誤解したか間違っていました。
mmv
一度に複数のファイルの名前を変更できますrename
。ただし、aroundrename
にはさまざまな方法で呼び出される2つのバージョンがあります。ここに多くの質問があるはずです。
答え4
たとえば、コマンドを実行するときにディレクトリにファイルがある場合、asd.txt
2つのファイルを名前付きディレクトリに移動しようとします。そのディレクトリがないため、エラーが報告されます。qwe.txt
mv *.txt *.tsv
*.tsv