web-dev-qa-db-ja.com

グロブパターンを持つcp隠しファイル

状況 :

$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat ‘foo/*’: No such file or directory)

隠しフォルダとファイルがいっぱいのディレクトリがあります。何が起こっており、解決策は何ですか?

13
Gradient

免責事項:この回答は特にBashを扱っていますが、その多くはグロブパターンに関する質問に適用されます!

スター文字(*)はワイルドカードです。それに代わる特定の文字セットがあり、ドットである最初の文字(.)はそれらの1つではありません。これは、Unixファイルシステムがどのように機能するかという特殊なケースであり、ドットで始まるファイルは「非表示」と見なされます。つまり、cplsなどのツールは、明示的に指示されない限り、それらを「表示」しません。

まず、サンプルデータをいくつか作成しましょう。

$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}

したがって、次のようになります。

$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3

それでは、ゲームをしてみましょう。コマンドechoを使用して、特定のワイルドカード(*)が次のような特定のコマンドに対してどのようになるかを一覧表示できます。

$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3


$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2

$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .dotdir*
.dotdir1 .dotdir2

行動を変える?

コマンドshopt -s dotglobを使用して*の動作を変更すると、regfile1などのファイルに加えて、.dotfile1にも一致するようになります。

bash manページからの抜粋

dotglob If set, bash includes filenames beginning with a `.' in the results 
        of pathname expansion.

例:

$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

次のコマンドでこの動作を元に戻すことができます:

$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3

あなたの状況は?

あなたは、パターン*に一致するすべてのファイルをコピーすることをcpに伝えていますが、ファイルはありません。

$ cp foo/.* .

または、fooフォルダ内のすべてが必要な場合は、次のようにできます。

$ cp foo .

または、明示的にすることもできます。

$ cp foot/.* foo/* .

bashでブレース展開を使用したよりコンパクトなフォーム:

$ cp foo/{.,}* .

いつでもechoトリックを使用して、提案されたファイルパターンを確認できます(これは、星が含まれているものの空想的な用語です)。

$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3

ちなみに、ファイルのディレクトリと他のディレクトリをコピーする場合は、通常、これを再帰的に行います。これは、-Rからcpへの切り替えです。

$ cp -R foo/. .
19
slm

zshを使用する場合の一般的な方法は、Dglob qualifier を使用することです([D] otファイルを含める):

cp foo/*(D) .

Dの有無にかかわらず、zshグロブには...も含まれないことにご注意ください(ご想像のとおり)。

31

シェルは*文字を解決するときにこれらのファイルを非表示として処理しているため、cpはこれらのファイル名を引数として受け取りません。

cp foo/.* .を明示的に指定することで、それらをコピーできます。

4
replay

すべてのファイルとディレクトリをある場所から別の場所にコピーしたい場合は、標準のrsyncコマンドを使用できます。上記の例では:

mkdir foo && touch foo/.test
rsync -a foo/ .

隠しファイルや隠しディレクトリを含むfooのすべての内容を再帰的に現在のディレクトリにコピーします。 foo/の末尾のスラッシュは、rsyncにとって重要です。これを使用すると、fooの内容のみがコピーされます。それがない場合、rsyncはfooもコピーします。例えば:-

mkdir src && mkdir dest && touch src/.test
rsync -a src  dest    // copies 'src' contents to 'dest/src'
rsync -a src/ dest    // copies 'src' contents to 'dest' 

マシン間のコピーを含む、Tweak rsyncには他にも多くのオプションがあります。

1
Rob Swarbrick

StéphaneChazelasのzsh answer は、グロブが含まれている単一の式では正しいです。ただし、デフォルトですべての式に設定する場合は、

setopt GLOB_DOTS

~/.zshrc永続化します。

1
Sparhawk