次の2つのファイルと1つのフォルダーがある場合:
someuser@computer:~/Desktop/test$ ls -l
total 340
-rw-r--r-- 1 someuser someuser 45082 ago 5 09:56 file1.pdf
-rw-r--r-- 1 someuser someuser 291836 ago 5 09:56 file2.pdf
drwxrwxr-x 2 someuser someuser 4096 ago 5 09:56 this_is_a_folder.pdf
そして、次のコマンドを実行します(宛先を省略していることに注意してください)。
cp *.pdf
file1.pdf
およびfile2.pdf
がthis_is_a_folder.pdf
フォルダーにコピーされます。
someuser@computer00:~/Desktop/test$ ls this_is_a_folder.pdf/
file1.pdf file2.pdf
明らかに*.pdf
は一致するアイテムに拡張されているので、
cp file1.pdf file2.pdf this_is_a_folder.pdf
... this_is_a_folder.pdf
はフォルダーなので、2つのファイルがそのフォルダーにコピーされます。
これはバグですか?
これは明らかにワイルドカード拡張の副作用であり、私が予期していることではありません。
missing destination file
errorを期待していました。
これはcp
コマンドのバグではありません。 cp *.pdf
を入力すると、ワイルドカードはcp
ではなくbash
によって展開されるため、cp
は実際のワイルドカードを表示しません。 cp
は、引数を1つだけ入力したことをどのようにして知るのですか?これはbashワイルドカードの副作用であり、バグとは言えません。
あなたは何が起こっているのかを完璧に理解しているようです。あなたの例では、_*pdf
_は実際に_file1.pdf file2.pdf this_is_a_folder.pdf
_に展開されます。何があなたを混乱させているのか分かりません。 cp
は、本来あるべきことを正確に実行しています。_file1.pdf
_および_file2.pdf
_を_this_is_a_folder.pdf
_にコピーするように指示しています。バグはなく、宣伝どおりに機能しています。
フォルダーの名前は_.pdf
_で終わるので、_*.pdf
_に含まれ、フォルダーと最後の引数(アルファベット順)であるため、cp
はファイルをそこにコピーします。期待どおりの動作を得るには、ワイルドカードをシェルから保護して、cp
がワイルドカードを見る前に展開されないようにする必要があります。
_$ cp "*pdf"
cp: missing destination file operand after `*pdf'
Try `cp --help' for more information.
_
この場合、ワイルドカードは展開されないため、cp
は実際に_*.pdf
_というファイルを探していることに注意してください。したがって、最後の引数としてディレクトリを指定して呼び出したとしても(_cp "*.pdf" foo/
_)、_cannot stat '*.pdf': No such file or directory
_について文句を言うでしょう。 _cp *pdf
_は1つだけに拡張されるため、_.pdf
_で終わるoneファイルのみが含まれるディレクトリで_*.pdf
_を試した場合も、予想される動作が表示されます引数:
_$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file1.pdf
$ cp *pdf
cp: missing destination file operand after `file1.pdf'
Try `cp --help' for more information.
_
これと比較してください:
_$ ls -l
total 0
drwxr-xr-x 1 terdon terdon 0 Aug 5 16:56 a_folder.pdf
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file1.pdf
-rw-r--r-- 1 terdon terdon 0 Aug 5 16:56 file2.pdf
$ cp *pdf
cp: target `file2.pdf' is not a directory
_
ここでは、フォルダーの名前がa
で始まるため、_*.pdf
_は_a_folder.pdf file1.pdf file2.pdf
_に展開されます。したがって、実際に実行されているcp
コマンドは
_cp a_folder.pdf file1.pdf file2.pdf
_
最後の引数がディレクトリではないため、エラーが返されます。
他の回答がすでに指摘したように、bashはワイルドカードを展開し、それをcp
に渡します。あなたの場合、cp
はfile1.pdf file2.pdf this_is_a_folder.pdf
を参照します。今それを防ぎましょう。
-t
、--target-directory
スイッチを使用して、ターゲットを指定します。ワイルドカードを使用した後は、常に最後に宛先を宣言してください。
cp *.pdf /I/want/to/copy/files/here
これはバグではなく、すべてのプログラムにワイルドカードを実装するのではなく、シェルでワイルドカード展開を1回実行することによる副作用です。
さて、これでいくつかのはるかに奇妙な方法があります。特に、名前が「-」で始まるファイルを作成することによって。例(空のディレクトリ内):
$ touch -- --version
$ ls
--version
$ rm *
rm (coreutils) 5.2.1
Written by Paul Rubin, David MacKenzie, Richard Stallman, and Jim Meyering.
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ls
--version
ワイルドカード「*」は、スイッチとして解釈されるファイル名に展開されます。
ファイル名にスペース、タブ、改行を入れることで混乱を引き起こすこともできます。
最後の部分パラメータがディレクトリの場合、cp
は指定されたファイルをそこにコピーします。ディレクトリに名前を付けても構いませんfoo.pdf
(なぜそのような名前なのか?!)。ワイルドカード展開は、ファイルタイプではなく、ファイル名(またはディレクトリ名)に基づいています。
2つの引数を使用すると、ターゲットはファイルまたはディレクトリのいずれかになります。ファイルの場合、ターゲットファイルは削除され、ソースファイルのコピーに置き換えられます。ターゲットがディレクトリの場合、ソースファイルのコピーがそのディレクトリに配置されます。指定された概要の1つに注意してください。
cp [OPTION]... [-T] SOURCE DEST
3つ以上の引数を指定すると、ターゲットはディレクトリとして扱われます。
cp [OPTION]... SOURCE... DIRECTORY