Переместите файл и оставьте мягкую ссылку


10

Я ищу одну команду Linux, которая позволяет мне сделать эквивалент этого:

cp /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

Если его нет, каков наилучший способ сделать это для нескольких файлов?


Я недостаточно хорошо знаю сценарии Bash, чтобы написать его, но мое решение было бы просто написать сценарий и назвать его чем-то броским, как cpln
Unkwntech

1
Не должен ли быть cp быть mv?
Барт ван Хейкелом

Опция -f для ln позаботится об этом.
INNAM

1
попробуйте это на 10
ГБ

2
@ Здравствуйте, вы путаете &&с &. Как написано, строка проверяет возвращаемое значение cp и запускает вторую часть только в случае успеха.
itadok

Ответы:


7

Небольшое замечание: вы можете использовать ln оба раза, чтобы команда фактически не перемещала данные (при условии, что оба пути находятся в одной файловой системе).

ln /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

Но я предполагаю, что вы хотите переместить содержимое / some / path / на другой диск, а затем создать ссылки на новые файлы, чтобы «никто» не заметил.

for f in `ls /some/path/`; do ln /some/path/$f /another/path/ && ln -sf /another/path/$f /some/path; done

Оборачиваем его в функцию bash:

function cpln {
    for f in `ls $1`
    do
        ln $1/$f $2 && ln -sf $2/$f $1
    done
}

Есть ли способ заставить это работать, если то, что я перемещаю, оказывается каталогом?
tladuke

Как это перемещает фактический файл на диске?
Ибрагим

Ибрагим: данные не перемещаются, они просто обновляют указатели в каталоге.
Мистер Акула

тладуке: да и нет. Так как каталог на диске намного меньше, нет необходимости в трюке ln (который не работает для каталогов), просто сделайте mv :-)
Мистер Акула

2

Вот мой сценарий, который вы можете использовать (принимает два параметра / some / path / file и / another / path /):

#!/bin/bash
cp $1 $2
if [ "$?" -ne "0" ]; then
    echo "Some error"
    exit 1
    fi
ln -sf $2/${1##*/} ${1%/*}

Классный трюк со струнными манипуляциями, никогда раньше такого не видел. Спасибо!
itadok

1

Серьезно, я думал, что это был действительно легкий вопрос.

Вот что я могу сделать в Perl:

#!/bin/perl
# Usage: cpln TARGETDIR SOURCE...
# Example: find tree/ -type f | xargs cpln commands/

$target = shift;

foreach(@ARGV) {
    m[(.*)/([^/]+)];
    system("cp $_ $target");
    system("ln -sf $target/$2 $1/");
}

Я надеялся на что-то более элегантное, но думаю, я воспользуюсь этим.


1
Чтобы сделать это «в Perl», вы должны использовать File :: Copy (или аналогичный) и symlink (). Perl не является оболочкой; избегайте system () и особенно избегайте передачи целых командных строк в system () (например, что если аргумент содержит пробел?). В любом случае, всегда, всегда ВСЕГДА проверяйте возвращаемые значения.
Джон Сиракуза
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.