現在のディレクトリを移動すると、「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:../general/を移動できません.' to。 ': デバイスまたはリソースが使用中です。

何のために.、そして..仕事の外でmv。 Unixで何かを移動すると、このmvコマンドは移動したいアイテムの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では、.コンポーネントまたはで終わるパスの名前を変更することは禁止されており..、次のエラーが返されると失敗します。

$ 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] 既存または新しいディレクトリと名付けられたディレクトリは、現在システムまたは他のプロセスで使用されており、実装はこれをエラーと見なします。

.現在プロセスで使用されていると考えることができます。ただし、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] パス引数にポイントである最後のコンポーネントが含まれています。

関連情報