web-dev-qa-db-ja.com

「mv *」はどこに移動するかをどのように知るのですか?

私はこのようなディレクトリ構造を持っていました:

ravikumar@ravikumar-RV409-RV509-RV709:~$ tree test
test
|
├── 1
├── 2
├── 3
├── 4
├── a
├── b
└── c

mvコマンドを次のように実行しました

ravikumar@ravikumar-RV409-RV509-RV709:~$ cd test/
ravikumar@ravikumar-RV409-RV509-RV709:~/test$ mv *

結果:

ravikumar@ravikumar-RV409-RV509-RV709:~/test$ tree
.        
|
└── c
    ├── 1
    ├── 2
    ├── 3
    ├── 4
    ├── a
    └── b

私の質問は、mv judgeがすべてのディレクトリとファイルを最後のディレクトリにどのように移動するかです。そしてそれはcです。

2
Ravikumar Wagh

そのディレクトリで実行した場合、mv *mv 1 2 3 4 a b cと同等でした。 -tオプションが存在しない限り、mvは最後の非オプション引数を宛先の名前として扱い、したがって1234a、およびb allを移動しますcに。

シェル は、*をファイル名のリストに展開します。この場合、実行中のコマンドには実際には*が表示されず、展開されたもののみが表示されます。 したがって、実行するコマンドはcannotは、実際に入力した内容に基づいて引数を処理する方法について判断します。シェルが渡すものだけが表示されます。

mv *を実行すると、おそらく推測されるように、ほとんど常に回避する必要があります。Shellとnotは、mvコマンド自体が*アルファベット順に展開します 名前が.で始まるものを除く、現在のディレクトリに含まれるすべてのファイルとディレクトリのリスト。

dotglobnullglob、およびnocaseglobシェルオプションとGLOBIGNORE変数を使用して、その動作をカスタマイズできます。詳細については、 ドキュメントを参照してください

cがディレクトリでない場合、コマンドは失敗し、何も移動せず、次のエラーメッセージが表示されます。

mv: target 'c' is not a directory

ただし、cはディレクトリであるため、コマンドが実行されるのを確認する以外の目的でコマンドを実行している場合でも、おそらくコマンドの最後に別のディレクトリの名前を書きますafter the *

mvがその引数が*から展開されたことを知る方法がない理由をより直感的に示すために、次のように書いたと仮定します。

mv 1 c

それは1cに移動します。ただし、2つのアイテムをcに移動したい場合があります。

mv 1 2 c

または5つのアイテム:

mv 1 2 3 4 a c

または6つのアイテム:

mv 1 2 3 4 a b c

ただし、シェルはmv *同じ順序でまったく同じ引数mvコマンドにmv 1 2 3 4 a b cとして渡すようにしました。

mvの1回の呼び出しで複数のアイテムを移動できないのは、多くの場合不便です。ただし、これが許可されず、常にエラーが発生した場合でも、2つのエントリのみが含まれるディレクトリで、同様に混乱する状況を作成できます。その後、そのディレクトリでmv *を実行すると、一方を他方に移動しようとします。

シェルが何を展開するのか疑問に思っている場合は、実行したいコマンドをprintf '%s\n'に置き換えることができます。これは、その後に渡されるすべての引数を改行で区切って出力します。例えば:

printf '%s\n' *
6
Eliah Kagan

この答えはいくつかのヒントを追加しています(しかし、主な答えは@Eliah Kaganによるものだと思います)。


物事を少し安全にするために、2つのエイリアスを作成しました。他のエイリアスの近くの~/.bashrcに保存します。

alias mv='mv -i'
alias rm='rm -i'

これらのエイリアスはコマンドをインタラクティブにし、上書き/削除するかどうかを尋ねます。

mvは、ターゲットを上書きするか、ターゲットが存在してファイルであるか、ターゲットがディレクトリで、同じ名前のファイルがすでに存在するかどうかを尋ねます。これは、たとえばワイルドカードmv *を使用する場合など、間違いを避けるのに役立ちます。


気づいてください

  • これらのエイリアスは、独自のユーザーIDでのみ機能します。 Sudoでは機能しません。 Sudoの後にエイリアスを展開する場合は、 個別に設定する にする必要があります。ルートシェルで特定のエイリアスを使用する場合(Sudo -sまたはSudo -iから取得する場合)、同様のエイリアスを作成して/root/.bashrcに保存する必要があります。

  • エイリアスをオーバーライド(およびmvおよびrmの元の動作を取得)するには、プレフィックス 'backslash`を使用します。

    \rm filename
    \mv filename1 filename2
    
  • -iフラグが自動的に渡されることに慣れて、誤った安全感を持つことがあります。たとえば、別のシステムを実行している場合、これらのエイリアスはアクティブではありません。

1
sudodus