回答:
最後の引数がディレクトリの場合、現在の作業ディレクトリ内のすべてのファイルとディレクトリ(名前がドットで始まるものを除く)をそのディレクトリに移動しただけです。2つのファイルがあった場合、最初のファイルが2番目のファイルを上書きした可能性があります。
デモは次のとおりです。
3つ以上のファイルで、最後の引数はファイルです
$ mkdir d1 d2 d3
$ touch a b c e
$ mv *
mv: target 'e' is not a directory
3つ以上のファイルで、最後の引数はディレクトリです
$ mkdir d1 d2 d3
$ touch a b c
$ mv -v *
'a' -> 'd3/a'
'b' -> 'd3/b'
'c' -> 'd3/c'
'd1' -> 'd3/d1'
'd2' -> 'd3/d2'
2つのファイル
$ touch a b
$ mv -v *
'a' -> 'b'
さらなる説明
シェルはglob(*
)をの引数に展開しmv
ます。通常、グロブはアルファベット順に展開されます。mv
常にファイルとディレクトリのリストが表示されます。グロブ自体を見ることはありません。
このコマンドmv
は、2種類の移動をサポートしています。1つはmv file ... directory
です。もう1つはmv old-file-name new-file-name
(またはmv old-file-name directory/new-file-name
)です。
まず、テストベースを作成します-5つのファイルと1つのフォルダー:
touch file1 file2 file3 file4 file5
mkdir folder
次に、テストコマンドを実行します。この-v
オプションは、シェルが実行するすべてのコマンドを印刷することを指定しますstderr
。-x
私は印刷された同じことをしたいのオプションは、stderr
- しかし、私はそれが行わたい後のコマンドが評価されているが、前シェルはそれを実行します。
sh -cxv 'echo mv *'
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
したがって、シェルにフィードするecho mv *
コマンドがあり、シェルが展開された後に 実行されるコマンドの後に、これらのファイルとフォルダーのすべて*
がecho mv
続きます。
デフォルトでは、シェルは次のようなグロブを展開します。
sh -cxv 'echo file[1-5]'
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
これは、set [+-]f
glob関数の結果です。
sh -cxvf 'echo file[1-5]'
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
そのmv *
ため、シェルなどのデフォルトオプションで構成されたシェルでコマンドを実行する*
と、現在のディレクトリ内のすべてのファイルの引数リストがロケールに従ってソートされた単語に展開されます。この引数リストexec(ve)
をmv
(基本的に)追加してsyscall を実行します。したがってmv
、シェルがそれらをグロブし、ソートするときに、すべての引数を取得します。strace
これらの効果を確認する以外に、次のようにデバッグを再度使用できます。
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
そして移植性:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
: /mv/file1/file2/file3/file4/file5/folder/
基本的に、シェルはmv
、ディレクトリの内容(空でなく、名前がで始まるファイル/フォルダを含まない場合.
)を引数リストとして実行します。mv
3つ以上の引数を指定して呼び出された場合、最終引数をディレクトリとして解釈するように指定されたPOSIXです-同じようln
に(実際、これらは基になる関数のツールに非常に似ているため)。
echo
しかし、十分なES:
sh -cxv 'mv *' ; ls
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
すべてのファイルは最後の引数に移動されました-これはフォルダーであるためです。それがフォルダーではない場合はどうなりますか?
sh -cxv 'cd *; mv *'; ls . *
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
この場合、POSIXの指定 方法はmv
次のとおりです。
mv [-if] source_file target_file
mv [-if] source_file... target_dir
最初の形式では、
mv
ユーティリティはsource_fileオペランドで指定されたファイルをtarget_fileで指定された宛先に移動します。この最初の形式は、最終オペランドが既存のディレクトリを指定せず、既存のディレクトリを参照するシンボリックリンクではない場合に想定されます。この場合、source_fileがディレクトリ以外のファイルを指定し、target_fileが末尾の/slash
文字で終わる場合、mv
これをエラーとして扱い、source_fileオペランドは処理されません。2番目の形式で
mv
は、source_fileオペランドで指定された各ファイルをtarget_dirオペランドで指定された既存のディレクトリ内の宛先ファイルに移動するか、target_dirが既存のディレクトリを参照するシンボリックリンクの場合に参照します。各source_fileの宛先パスは、ターゲットディレクトリ、/slash
ターゲットがa/slash
で終わっていない場合は単一の文字、およびsource_fileの最後のパス名コンポーネントの連結です。この2番目の形式は、最終オペランドが既存のディレクトリを指定するときに想定されます。
したがって、次のように*
展開する場合:
2つのファイル
renamed
、2番目のファイルは1 番目から2番目ですunlinked
。最後にディレクトリまたは1つへのリンクが続く1つ以上のファイル
他に何か
sh
、私はそれでデバッグするのを忘れましたが、私の元の質問に関しては、問題はシェルではないことを意味しmv
ますか?それは厄介で、当初考えていたよりも簡単ですが、本当のtrapです。
*
単一の引数ではありませんか?右?:)
最初に、シェルは./*
現在のディレクトリ内のすべてのファイルに展開します(ドットで始まるファイルを除く)。
mv
が1つのみの場合:失敗mv
失敗します。echo ./*
doを呼び出すだけで、シェルが使用する順序(通常はアルファベット順)を確認できます。
mv
1つの引数のみで呼び出された場合、エラーメッセージを返します。
missing destination file operand after *filename*
昨日はそうではありませんでしたが、私の歴史からの同じコマンドが今では与えます。
何を
mv *
するの?
短い答えは次のとおりです。
シェルは、ワイルドカード*
をディレクトリの内容のリストに展開します。次に、シェルはその完全なリストをコマンドに渡します。コマンドは決して見えません*
。
このコマンドmv file1 file2 ... filen directory
は、file1 ... filenをディレクトリに移動します。
ここでは、3つのファイルを含むテストディレクトリを作成します
$ mkdir t
$ cd t
$ echo a>a; echo b>b; echo c>c
$ ls
a b c
複数のファイルを単一のファイルに移動することはできません
$ mv *
mv: target `c' is not a directory
サブディレクトリを追加しましょう
$ mkdir d
あなたはできる subdiretoryに複数のファイルを移動します
$ mv *
$ ls
d
$ ls d
a b c
mv file1 file2 ... filen directory
が関係することはほとんどありません*
。
*
しfile dir
ないことです。d
f
a b c d
ではないfile ... dir
です。あなたはどこにもソートについて言及せず、それが起こるだけに*
なると言うので、私はまったくコメントしましたfile ... dir
。