現在のディレクトリを移動すると、「mv: `.' を `../dir/.' に移動できません: デバイスまたはリソースがビジーです」というメッセージが表示されます。

現在のディレクトリを移動すると、「mv: `.' を `../dir/.' に移動できません: デバイスまたはリソースがビジーです」というメッセージが表示されます。
$ mv . ../general/
mv: cannot move `.' to `../general/.': Device or resource busy

現在のディレクトリがビジー状態のデバイスまたはリソースであり、移動できないことを意味しますか? それはなぜですか?

答え1

現在いるディレクトリを移動することはできません。現在のプロセスがビジー状態を維持しています。

代わりに、1 つ上のレベルに移動し、以前の現在のディレクトリに名前を付けて、ターゲットに移動します。

答え2

ドットを移動することはできません.。ドットは現在のディレクトリ名と同じではありません。ドットはディレクトリへのポインタとして考えることができます.が、ディレクトリ自体として考えることはできません。したがって、

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp
/home/jimmij/tmp
/home/jimmij/tmp
$ mkdir tmp1 tmp2
$ mv tmp1/. tmp2/
mv: cannot move ‘tmp1/.’ to ‘tmp2/.’: Device or resource busy

動作しませんが

cd tmp1
mv ../tmp1 ../tmp2

問題なく動作するので、実際にはできる現在のディレクトリを移動しますが、この操作の後にいくつかのコマンドが混乱する可能性があります。

$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp1
/home/jimmij/tmp/tmp2/tmp1
$ cd .
$ pwd && echo $PWD && realpath .
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1
/home/jimmij/tmp/tmp2/tmp1

..、つまり親ディレクトリの場合も同様です。

つまり、各ディレクトリには少なくとも 2 つの要素 (.と) が含まれている必要があります..。これらを移動または削除することはできません。

答え3

メッセージが表示される理由:

mv: .' to../general/ を移動できません。': デバイスまたはリソースがビジーです

.は、、および..が に加えてどのように機能するかによるものですmv。 Unix で何かを移動すると、mvコマンドは移動しようとしているアイテムの inode を参照するすべてのリンクを解除しようとします。 この場合、それは参照しているディレクトリの inode になります.

「シンボル/リンク」.と は..inode にリンクしており、ある意味では特別です。これらの歴史については、次のタイトルの U&L Q&A で読むことができます。新しいディレクトリに何かが追加される前に、ハード リンクの数が 2 になるのはなぜですか?.新しく作成されたディレクトリを見たことがあるなら、リンク数が常に 2 で始まることに気付くでしょう。その理由は、およびが存在するためです..

$ mkdir adir

$ ls -l | grep adir
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 adir

$ ls -la adir/
total 8
drwxrwxr-x. 2 saml saml 4096 Oct  5 08:02 .
drwxrwxr-x. 3 saml saml 4096 Oct  5 08:02 ..

注記:ls不明な点がある場合は、次の U&L Q&A に出力の参照があります。ls -al 出力のフィールドはどういう意味ですか?

したがって、これらは実際のディレクトリの名前ではなく、ディレクトリにリンクしている「シンボル/リンク」です。したがって、使用する前にリンクを解除する必要がありますmv

コマンドは を使用しているため.、 コマンドによってリンクを解除することはできませんmv。そのため、メッセージ「デバイスまたはリソースがビジーです」が表示されます。

参考文献

答え4

.Linux では、 またはコンポーネントで終わるパスの名前変更は禁止されており..、EBUSY エラーが返されます。次の例も失敗します。

$ mkdir a a/aa
$ mv a/aa/.. b
mv: cannot move ‘a/aa/..’ to ‘b/..’: Device or resource busy

このコードは にあります。さまざまな関数に渡されるパス名の最後のコンポーネントは、やではなく、namei.c::renameat型である必要があります。LAST_NORMLAST_DOTLAST_DOTDOT

FreeBSD は、これらの各ケースでエラー EINVAL を返します。


なぜこのような制限があるのか​​は推測することしかできません。

rename() 関数は次の場合に失敗します:
...
[EBUSY] old または new で指定されたディレクトリが現在システムまたは別のプロセスによって使用されており、実装ではこれをエラーと見なします。

.プロセスによって現在使用中であると考えることもできます。ただし、Linux では次のことが許可されているため、ディレクトリが何らかのプロセスによって使用されているだけではrename失敗には至らないことに注意してください。

$ mkdir /tmp/t
$ cd /tmp/t
$ mv /tmp/t /tmp/t1
$ /bin/pwd
/tmp/t1

.との名前変更を禁止する理由は、..おそらく「ユーザーの混乱を減らすため」です。

  • .通常は、親ディレクトリのエントリへのハードリンクであり、プロセスが常に開いて.現在の作業ディレクトリにアクセスできるという点でやや特殊です。名前を変更できると逆効果になります。
  • ..通常はディレクトリの親へのハードリンクであり、プロセスを開くと..親ディレクトリ(またはマウントポイントの場合はディレクトリ自体)が取得されるという点でやや特殊です。名前を変更できると逆効果になります。

Linuxでは、最後のコンポーネントが(ENOTEMPTY)または(EINVAL)rmdirであるパスも禁止されています。FreeBSDは、これらのそれぞれに対してエラーEINVALを返します。...rmdir の POSIX 標準には次のものがあります:

rmdir() 関数は次の場合に失敗します:
...
[EINVAL] パス引数の最後のコンポーネントにドットが含まれています。

関連情報