web-dev-qa-db-ja.com

ワイルドカードを含む単一の引数を持つcp

次の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.pdfthis_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 fileerrorを期待していました。

18

これはcpコマンドのバグではありません。 cp *.pdfを入力すると、ワイルドカードはcpではなくbashによって展開されるため、cpは実際のワイルドカードを表示しません。 cpは、引数を1つだけ入力したことをどのようにして知るのですか?これはbashワイルドカードの副作用であり、バグとは言えません。

52
Kartik

あなたは何が起こっているのかを完璧に理解しているようです。あなたの例では、_*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
_

最後の引数がディレクトリではないため、エラーが返されます。

22
terdon

他の回答がすでに指摘したように、bashはワイルドカードを展開し、それをcpに渡します。あなたの場合、cpfile1.pdf file2.pdf this_is_a_folder.pdfを参照します。今それを防ぎましょう。

  • ワイルドカードは使用しないでください。
  • -t--target-directoryスイッチを使用して、ターゲットを指定します。
  • ワイルドカードを使用した後は、常に最後に宛先を宣言してください。

    cp *.pdf /I/want/to/copy/files/here
    
9
Braiam

これはバグではなく、すべてのプログラムにワイルドカードを実装するのではなく、シェルでワイルドカード展開を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

ワイルドカード「*」は、スイッチとして解釈されるファイル名に展開されます。

ファイル名にスペース、タブ、改行を入れることで混乱を引き起こすこともできます。

8
pjc50

最後の部分パラメータがディレクトリの場合、cpは指定されたファイルをそこにコピーします。ディレクトリに名前を付けても構いませんfoo.pdf(なぜそのような名前なのか?!)。ワイルドカード展開は、ファイルタイプではなく、ファイル名(またはディレクトリ名)に基づいています。

2つの引数を使用すると、ターゲットはファイルまたはディレクトリのいずれかになります。ファイルの場合、ターゲットファイルは削除され、ソースファイルのコピーに置き換えられます。ターゲットがディレクトリの場合、ソースファイルのコピーがそのディレクトリに配置されます。指定された概要の1つに注意してください。

cp [OPTION]... [-T] SOURCE DEST

3つ以上の引数を指定すると、ターゲットはディレクトリとして扱われます。

cp [OPTION]... SOURCE... DIRECTORY
4
Lekensteyn