Почему перемещение каталога с символической ссылкой A в каталог с символической ссылкой B приводит к перемещению A внутрь B?

Сценарий: я пишу сценарий оболочки, который проверяет, существует ли каталог; если это так, и это символическая ссылка, он переименовывает каталог с добавлением .bak к имени каталога. Однако я заметил, что если я перемещаю каталог с символической ссылкой (каталог A) в другой каталог с символической ссылкой (B), это вызывает перемещение A внутри B, а не перезапись B.

Проиллюстрировать:

$ mkdir foo                                                                     
$ mkdir bar                                                                     
$ ln -s "$PWD/foo" ~/.baz                                                       
$ ls -al ~/.baz                                                                 
lrwxr-xr-x  1 ysim  staff  15 Sep 11 21:45 /Users/ysim/.baz -> /Users/ysim/foo  
$ mv ~/.baz ~/.bam                                                              
$ ls -al ~/.bam                                                                 
lrwxr-xr-x  1 ysim  staff  15 Sep 11 21:45 /Users/ysim/.bam -> /Users/ysim/foo  
$ ls -al ~/.baz                                                                 
ls: /Users/ysim/.baz: No such file or directory                                                                                                   
$ ln -s "$PWD/bar" ~/.baz                                                       
$ ls -al ~/.baz                                                                 
lrwxr-xr-x  1 ysim  staff  15 Sep 11 21:47 /Users/ysim/.baz -> /Users/ysim/bar  
$ ls -al ~/.bam                                                                 
lrwxr-xr-x  1 ysim  staff  15 Sep 11 21:45 /Users/ysim/.bam -> /Users/ysim/foo  

Теперь, когда я переименовываю/перемещаю ~/.baz в ~/.bam:

$ mv ~/.baz ~/.bam                 

Цель ~/.baz (/Users/ysim/bar) не перемещается к цели ~/.bam, как ожидалось:

$ ls -al ~/.bam                                                                 
lrwxr-xr-x  1 ysim  staff  15 Sep 11 21:45 /Users/ysim/.bam -> /Users/ysim/foo 

Вместо этого вся символическая ссылка ~/.baz была перемещена внутри каталога ~/.bam:

$ ls -al ~/.bam/
total 8
drwxr-xr-x   3 ysim  staff   102 Sep 11 21:47 .
drwxr-xr-x+ 96 ysim  staff  3264 Sep 11 21:51 ..
lrwxr-xr-x   1 ysim  staff    15 Sep 11 21:47 .baz -> /Users/ysim/bar

Почему это? И как мне сделать то, что я намеревался сделать, а именно записать цель ~/.baz в цель ~/.bam, чтобы ~/.bam имел место назначения /Users/ysim/bar?


person 3cheesewheel    schedule 12.09.2013    source источник


Ответы (1)


Это работает так, потому что mv просит ОС выполнить перемещение, а ОС разыменовывает символические ссылки. Чтобы вести себя по-другому, mv потребуется дополнительный код для проверки символических ссылок и некоторых параметров --dereference-target, --dereference-src (или подобных). Подумайте о количестве различных моделей поведения, которые могут оказаться желательными для разных пользователей.

Тебе нужно

rm "$dest"
cp -a "$src" "$dest"
# in your case src=".bam" and dest=".baz"

Кстати, если в сценарии вы хотите

  • "читать" цель символической ссылки в скрипте: target=$(readlink "$f")
  • проверить, является ли файл символической ссылкой: test -l "$f"
person dan3    schedule 12.09.2013
comment
Ах я вижу. Так, например — и поправьте меня, если я ошибаюсь — будет неясно, хотите ли вы переместить источник A в источник B, как я хочу сделать (~/.bam -> /Users/ysim/bar), или цель A в цель B (~/.baz -> /Users/ysim/foo), или полностью удалить ~/.bam (только ~/.baz -> ~/bar). - person 3cheesewheel; 12.09.2013
comment
Было бы неясно, если mv решил сделать что-то помимо того, что предоставляет OS/libc. Но mv нет, вероятно, потому что, как вы сказали, будет много запутанных вариантов :) - person dan3; 12.09.2013