Intereting Posts

Создание нескольких символических ссылок при сохранении структуры каталогов

Я хочу генерировать символические ссылки из нескольких папок, сохраняя структуру каталогов. Я прочитал несколько ответов, и самое лучшее, что я могу придумать, это:

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f -exec ln -sf \{\} . \; 

Это создает символические ссылки в одном каталоге. Но я хочу иметь ту же структуру каталогов, что и в команде find и, если возможно, использовать ту же структуру, что и вход. Например: input/*/Clean_data/*/*/*.fq.gz

Когда файлы и каталоги совпадают, символическая ссылка должна следовать той же структуре, что и абсолютная ссылка, найденная с помощью команды find .

Любой вход оценивается.

Я могу сгенерировать команды с awk а затем передать их в bash :

 find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f | \ awk '{printf "mkdir -p `dirname %s`\nln -s %s ./%s \n", substr($0, 27), $0, substr($0, 27)}' 

Это генерирует список команд, я бы сначала их контролировал, а затем, наконец, подключил к bash . Полная команда:

 find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f | \ awk '{printf "mkdir -p `dirname %s`\nln -s %s ./%s \n", substr($0, 27), $0, substr($0, 27)}' | bash 

Уродливый и хрупкий, но он должен выполнить свою работу:

 find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f -print0 | \ xargs -0 -n 1 \ sh -c 'mkdir -p "$PWD/`dirname $0`"; ln -s "$0" "$PWD/`dirname $0`"' 

Вдохновленный ответом хаоса , я придумал эту альтернативу, которая также обрезает ненужные каталоги :

 find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f \ -printf 'mkdir -p "${PWD}/%h"; ln -s "%p" \\\n\t"${PWD}/%h"\n' | \ sed 's#/data/DIV5/SASC/e042_ctcl##' | \ sh - 

Он генерирует требуемые команды mkdir и ln :

 mkdir -p "${PWD}//data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a"; ln -s "/data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a/foobar.fq.gz" \ "${PWD}//data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a" 

Затем он удаляет ненужные каталоги из них с помощью sed , в результате чего:

 mkdir -p "${PWD}//input/x/Clean_data/0/a"; ln -s "/data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a/foobar.fq.gz" \ "${PWD}//input/x/Clean_data/0/a" 

Команда ln запускается в той же строке, что и mkdir, и продолжается на следующей строке, чтобы сохранить источник неповрежденным при обрезке адресата. Печать их на одной и той же строке или каждой отдельной строки потребовала бы более сложного сценария sed .

Объяснение из документации для поиска , параметров -printf :

%p Имя файла (не абсолютное имя пути, а имя файла, с которым он был найден, – это относительный путь от одной из начальных точек).

%h Ведущие каталоги имени файла (все кроме последнего элемента и косой черты перед ним). Если имя файла не содержит косой черты (например, поскольку оно было названо в командной строке и находится в текущем рабочем каталоге), то «% h» расширяется до «.». Это предотвращает «% h /% f», расширяющееся до «/ foo», что было бы удивительно и, вероятно, нежелательно.

У меня создается впечатление, что вы ищете инструмент вроде GNU Stow .

GNU Stow является менеджером фермы символических ссылок, который принимает различные пакеты программного обеспечения и / или данных, расположенных в отдельных каталогах в файловой системе, и заставляет их быть установленными в одном месте. Например, /usr/local/bin может содержать символические ссылки на файлы в /usr/local/stow/emacs/bin , /usr/local/stow/perl/bin и т. Д., А также рекурсивно для любых других подкаталогов, таких как .../share , .../man и т. д.

Проверьте это, если он соответствует прецеденту.

Zsh имеет удобную функцию zmv . Сначала загрузите его (вы можете сделать это из своего .zshrc или в командной строке для .zshrc использования):

 autoload -U zmv alias zcp='zmv -C' alias zln='zmv -L' 

Воспроизведение леса символических ссылок так же просто:

  zln -s '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/*/*/*.fq.gz)' '$1' 

Если вы хотите рекурсивно перемещать Clean_data а не только ровно на два уровня:

  zln -s '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1' 

Существует большое ограничение: это не приведет к созданию необходимых подкаталогов. Вы можете это сделать, определив и используя функцию обертки для ln которая создает каталоги по мере необходимости.

 ln_s_mkdir () { mkdir -p -- ${(P)#} ln -s "$@" } zmv -p ln_s_mkdir '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1' 

Вы можете сделать команду немного быстрее, используя внутренние команды mkdir и ln zsh (которые не загружаются по умолчанию, потому что у них меньше вариантов, которые утилиты GNU обнаруживают в большинстве систем).

 zmodload -F zsh/files b:zf_ln b:zf_mkdir ln_s_mkdir () { zf_mkdir -p -- ${(P)#} zf_ln -s "$@" } zmv -p ln_s_mkdir '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1'