Символы по глубине каталога

У меня есть следующая структура каталогов, которую мне нужно создать, и при этом мне также нужно создать zip-файлы, которые являются символическими ссылками.

/a/2015-08-17/a.zip /a/2015-08-17/a_b/a_b.zip /a/2015-08-17/a_b/a_b_c/a_b_c.zip /a/2015-08-17/a_b/a_b_c/a_b_c_1/a_b_c_1.zip /a/2015-08-17/a_b/a_b_c/a_b_c_2/a_b_c_2.zip /a/2015-08-17/a_b/a_b_c/a_b_c_3/a_b_c_3.zip 

Архивы 1stdepth.zip, 2nddepth.zip и т. Д. Существуют и одинаковы каждый раз. Мне дана структура каталогов, как выше, и мне нужно создать следующие символические ссылки в соответствии с глубиной в структуре каталогов.

 ln -s 1stdepth.zip /a/2015-08-17/a.zip ln -s 2nddepth.zip /a/2015-08-17/a_b/a_b.zip ln -s 3rddepth.zip /a/2015-08-17/a_b/a_b_c/a_b_c.zip ln -s 4thdepth.zip /a/2015-08-17/a_b/a_b_c/a_b_c_1/a_b_c_1.zip ln -s 4thdepth.zip /a/2015-08-17/a_b/a_b_c/a_b_c_2/a_b_c_2.zip ln -s 4thdepth.zip /a/2015-08-17/a_b/a_b_c/a_b_c_3/a_b_c_3.zip 

Как мне это сделать в сценарии? Должен ли я считать / на пути и осознать, в какой глубине я? Есть ли более разумный способ сделать это? Я использую Solaris.

4 Solutions collect form web for “Символы по глубине каталога”

Вот как я решил свою проблему. Это может быть не самый лучший способ, но мне нужно быстрое решение. Может, кому-то это понадобится

 #!/usr/bin/bash function main() { [ $# -ne 1 ] && { echo "Usage: $0 file"; exit 1; } depth1=/a.zip depth2=/b.zip depth2_special=/special.zip depth3=/c.zip depth4=/d.zip cat $1 | while read line; do #Count the number of occurences of / in each line x=`echo $line |awk -F/ '{c += NF - 1} END {print c}'` if [ $x -eq 13 ] ;then echo "The path has 13 / " ln -sf $depth4 $line else if [ $x -eq 12 ] ;then echo "The path has 12 /" ln -sf $depth3 $line else if [ $x -eq 11 ] ; then echo "The path has 11 /" #If there is no _ in the file path treat it as a special case underscore=`echo $line |awk -F_ '{c += NF - 1} END {print c}'` if [ $underscore -eq 1 ] ; then ln -sf $depth2 $line else ln -sf $depth2_special $line fi; else if [ $x -eq 10 ] ;then echo "The path has 10 /" ln -sf $depth1 $line else echo "Error - the path is not correct" fi; fi; fi; fi; done } main "$@" 

Я полагаю, что команда tree в linux может помочь вам в получении глубины Справочника и приземлении вашей проблемы как-то.

Ps: Я понятия не имею о Solarix, но на Debian мы имеем команду tree

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

Во-первых, все, что нам нужно сделать, происходит в каталоге /a/2015-08-17 . Итак, давайте перейдем к этому каталогу.

 cd /a/2015-08-17 

Теперь нам нужно создать кучу символических ссылок на основе существующих каталогов. (Я предполагаю, что каталоги уже существуют, так как вы не объясняете, как определить, какие каталоги создавать.) Основная команда, чтобы сделать что-то во всех подкаталогах текущего каталога,

 find . -type d … 

Нам нужно создать символическую ссылку на основе глубины каталога. Название символической ссылки – это базовое имя каталога плюс .zip в конце (за исключением того, что это a.zip ), а цель вычисляется по глубине. Сначала сделаем имя ссылки.

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

 find . -type d -exec sh -c '???' {} \; 

Путь к каталогу (начиная с . ) Доступен в скрипте как $0 . Если $0 справедлив . , нам нужно создать a.zip .

 find . -type d -exec sh -c ' if [ "$0" = "." ]; then ln -s 1stdepth.zip a.zip; fi ' {} \; 

В противном случае нам нужно извлечь базовое имя каталога. Это можно сделать с помощью конструкции расширения параметра оболочки ${0##*/} (значение $0 минус самый длинный префикс, заканчивающийся на a):

 find . -type d -exec sh -c ' if [ "$0" = "." ]; then ln -s 1stdepth.zip a.zip else ln -s ???depth.zip "$0/${0##*/}.zip" fi ' {} \; 

Теперь нам нужно рассчитать глубину. Это число косых черт в $0 плюс один, так как корень имеет глубину 1. Один из способов подсчета числа косых черт – удалить все остальные символы и подсчитать длину оставшегося.

 find . -type d -exec sh -c ' depth=$(printf %s "$0" | tr -dc / | wc -c) if [ "$0" = "." ]; then ln -s 1stdepth.zip a.zip else ln -s $((depth+1))???depth.zip "$0/${0##*/}.zip" fi ' {} \; 

Почти готово; нам нужно вычислить суффикс, чтобы получить 1-й, 2-й и т. д.

 find . -type d -exec sh -c ' depth=$(($(printf %s "$0" | tr -dc / | wc -c) + 1)) if [ "$0" = "." ]; then ln -s 1stdepth.zip a.zip else case $depth in *1?) suffix=th;; *1) suffix=st;; *2) suffix=nd;; *3) suffix=rd;; *) suffix=th;; esac ln -s "${depth}${suffix}depth.zip" "$0/${0##*/}.zip" fi ' {} \; 

С zsh (дополнительный пакет на Solaris), используя типичный синтаксис только для записи:

 $ for i (*/**/*(/)) echo ln -s -- $((${#${(s:/:)i}}-1))??depth.zip $i/${${i%/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]}:t}.zip ln -s -- 1stdepth.zip a/2015-08-17/a.zip ln -s -- 2nddepth.zip a/2015-08-17/a_b/a_b.zip ln -s -- 3rddepth.zip a/2015-08-17/a_b/a_b_c/a_b_c.zip ln -s -- 4thdepth.zip a/2015-08-17/a_b/a_b_c/a_b_c_1/a_b_c_1.zip ln -s -- 4thdepth.zip a/2015-08-17/a_b/a_b_c/a_b_c_2/a_b_c_2.zip ln -s -- 4thdepth.zip a/2015-08-17/a_b/a_b_c/a_b_c_3/a_b_c_3.zip 

Удалите «эхо», чтобы на самом деле это сделать.

Небольшой разрыв функций zsh:

  • for f (...) cmd : короткая форма for i in ...; do ...; done for i in ...; do ...; done for i in ...; do ...; done . Только синтаксическая разница.
  • **/* : рекурсивный glob ( некоторые другие оболочки скопировали это с тех пор )
  • (/) : glob qualifier: здесь выберите только файлы каталога типов. С другими оболочками вы можете сделать */ хотя это также будет включать символические ссылки в каталоги.
  • ${(s:/:)i} : флаги расширения переменных. Здесь s разбивается на / .
  • ${#${...}} : расширения zsh обычно могут быть вложенными. Здесь ${#array} возвращает количество элементов в массиве, поэтому для a/b/c , 3.
  • ${var:t} : как в csh, верните хвост (базовое имя).

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

 ln -s -- /path/to/1stdepth.zip a/2015-08-17/a.zip 

Это легко решить, добавив $PWD :

 for i (*/**/*(/)) echo ln -s -- $PWD/$((${#${(s:/:)i}}-1))??depth.zip $i/${${i%/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]}:t}.zip 

Или, вероятно, лучше, относительная ссылка:

 ln -s ../../1stdepth.zip a/2015-08-17/a.zip 

Что вы можете сделать с:

 setopt extendedglob for i (*/**/*(/)) { z=($((${#${(s:/:)i}}-1))??depth.zip) echo ln -s -- ${i//[^\/]##/..}/$z $i/${${i%/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]}:t}.zip } 

С помощью ${i//[^\/]##/..} мы заменяем последовательности символов без косой черты на.

(обратите внимание, что эти -- не нужны для Solaris, но будут на GNU-системах, если могут быть каталоги, чье имя начинается с - ).

  • Как я могу перечислить файлы, из которых нет символических ссылок?
  • Как отключить файл, символически привязанный к себе, без разрушения
  • Выполнить команду, которая возвращает строку при чтении файла
  • Предварительная настройка целевого каталога GNU Stow по умолчанию
  • Как скопировать символические ссылки как символические ссылки с одной машины на другую?
  • rsync --link-dest не работает, как ожидалось, с символическими ссылками
  • Что произойдет, если случайно переместить мягкую ссылку, а затем «/»?
  • Трассировка маршрута символической ссылки
  • Почему режим cp --no-preserve = сохраняет режим? Доступны альтернативные инструменты?
  • Символическая ссылка становится нечитаемой после prctl (PR_SET_DUMPABLE, 0);
  • Git не перезаписывает символическую директорию при проверке филиала
  • Linux и Unix - лучшая ОС в мире.