В сценарии оболочки, Как передать переменную другое значение после выполнения одного задания?

Я пытаюсь создать скрипт, который увидит, существует ли каталог, и будет хранить все его содержимое под ним в соответствии с именем / контуром каталога.

Дальше я мог пойти –

#!/system/bin/sh -xv Z="$PWD/../WorkingDir"; T='320'; F='480'; I='540'; D='dark'; L='light'; P='play'; cd $Z; if [ -d $T/$D ]; then R=""$T"_"$D".zip"; else if [ -d $T/$L ]; then R=""$T"_"$L".zip"; else R="file.zip"; fi fi; for dir in */*/; do #Skip directories where the zip already exists [ -e "$dir"/"$R" ] || ( cd -- "$dir" && zip -0rq "$R" .) done 

Но это происходит –

 #!/system/bin/sh -xv ... . . if [ -d $T/$D ]; then R=""$T"_"$D".zip"; else if [ -d $T/$L ]; then R=""$T"_"$L".zip"; else R="file.zip"; fi fi; + [ -d 320/dark ] + R=320_dark.zip for dir in */*/; do #Skip directories where the zip already exists [ -e "$dir"/"$R" ] || ( cd -- "$dir" && zip -0rq "$R" .) done + [ -e 320/dark//320_dark.zip ] + cd -- 320/dark/ + zip -0rq 320_dark.zip . + [ -e 320/light//320_dark.zip ] + cd -- 320/light/ + zip -0rq 320_dark.zip . . . ...and so on.. , #!/system/bin/sh -xv ... . . if [ -d $T/$D ]; then R=""$T"_"$D".zip"; else if [ -d $T/$L ]; then R=""$T"_"$L".zip"; else R="file.zip"; fi fi; + [ -d 320/dark ] + R=320_dark.zip for dir in */*/; do #Skip directories where the zip already exists [ -e "$dir"/"$R" ] || ( cd -- "$dir" && zip -0rq "$R" .) done + [ -e 320/dark//320_dark.zip ] + cd -- 320/dark/ + zip -0rq 320_dark.zip . + [ -e 320/light//320_dark.zip ] + cd -- 320/light/ + zip -0rq 320_dark.zip . . . ...and so on.. , #!/system/bin/sh -xv ... . . if [ -d $T/$D ]; then R=""$T"_"$D".zip"; else if [ -d $T/$L ]; then R=""$T"_"$L".zip"; else R="file.zip"; fi fi; + [ -d 320/dark ] + R=320_dark.zip for dir in */*/; do #Skip directories where the zip already exists [ -e "$dir"/"$R" ] || ( cd -- "$dir" && zip -0rq "$R" .) done + [ -e 320/dark//320_dark.zip ] + cd -- 320/dark/ + zip -0rq 320_dark.zip . + [ -e 320/light//320_dark.zip ] + cd -- 320/light/ + zip -0rq 320_dark.zip . . . ...and so on.. 

Каждый файл получает то же имя ( 320_dark.zip в этом случае). Я хочу, чтобы он отличался (в зависимости от имени папки / пути) для каждого файла, который застегивается.

Я хотел –

 + [ -d 320/dark ] + R=320_dark.zip 

– каждый раз менять каждую папку. Как и должно быть 320_light.zip для пути папки 320/light .

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

 + [ -e 320/dark//320_dark.zip ] + cd -- 320/dark/ + zip -0rq 320_dark.zip . + [ -e 320/light//320_light.zip ] + cd -- 320/light/ + zip -0rq 320_light.zip . 

2 Solutions collect form web for “В сценарии оболочки, Как передать переменную другое значение после выполнения одного задания?”

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

 #!/system/bin/sh -xv cd "$PWD/../WorkingDir" compress() { # Detect only known dir names, convert slash to underscore local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')" # Set a default value to the variable : ${arch:=file} # Only create a ZIP archive if not present in the parent directory # Note $PWD is evaluated *before* cd [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." ) } for dir in */*/; do compress $dir done 

Просто измените строку sed чтобы добавить то, что я назвал «известными именами каталогов».


EDIT : добавление нескольких объяснений в соответствии с запросом OP.

Скрипт проверяет условия до того, как каталоги zipping каждый раз, когда новый каталог найден в цикле for . Переменные также были устранены. Давайте проанализируем код.

Основной цикл

 cd "$PWD/../WorkingDir" for dir in */*/; do # Ensures to select only directories compress $dir # compress runs some checks prior to compressing done 

На самом деле не так много сказать об этом.

Процедура compress

 local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')" 

$1 – аргумент, переданный в compressed , то есть каталог для проверки и сжатия. Что делает sed первую очередь ( '/320\/(light|dark)/' ), проверьте, имеет ли путь форму

 320/light 320/dark 

и возвращает путь с косой чертой, преобразованной в символ подчеркивания: 's@/@_@g' . Использование знака at в качестве разделителя для удобства чтения, чтобы избежать слэш. Другими допустимыми обозначениями являются 's:/:_:g' или 's#/#_#g' или классический 's/\//_/g' . Обратите внимание, что слэш для преобразования экранируется с помощью анти-косой черты. Тем не менее, я считаю, что последняя форма менее читаема.

Конечный p работает вместе с sed -n ; последний вариант в данном конкретном случае означает « не отгонять ничего, если не будет указано p когда будет найдено совпадение (т. е. в закрывающих косых чертах) ». Поэтому arch будет содержать путь с косой чертой, преобразованной в символ подчеркивания, если и только если в пути найдено регулярное выражение 320\/(light|dark) . В противном случае это ничего не даст, сделав arch пустой переменной.

Опция -r – удобный способ сказать sed использовать канонические регулярные выражения, более читаемые. В противном случае вам нужно будет избежать символов скобок и труб. Я нахожу '/320\/(light|dark)/s@/@_@gp' более читаемым, чем '/320\/\(light\|dark\)/s@/@_@gp' или '/320\/\(light\|dark\)/s/\//_/gp' .

 : ${arch:=file} 

Эта строка устанавливает arch в значение по умолчанию «файл», если оно пустое. Странная конструкция требуется, потому что только ${arch:=file} запускает синтаксическую ошибку. Двоеточие сообщает оболочке ничего не делать (:), но назначить arch значение, если оно пустое.

  [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." ) 

Здесь я использовал -f вместо -e потому что первый также проверяет файлы с нулевой длиной. Тест будет успешным только в том случае, если существует ZIP-архив и имеет ненулевую длину.

Если в родительском (или текущем ) каталоге сценария нет файла архива, или если его размер равен нулю, тогда скрипт порождает под-оболочку, которая изменяется в каталог, переданный в качестве аргумента для compress и застегивания его содержимого. Обратите внимание, что переменные $1 и $PWD оцениваются до того, как подчиненная оболочка выполнит свои инструкции, то есть $PWD будет равна родительскому каталогу $Z в вашей начальной версии.

Расширение фильтра

Вы можете действовать следующим образом:

 sed -rne '/320\/(light|dark|play)/s@/@_@gp' 

для проверки имен каталогов, таких как

 320/light 320/dark 320/play 

Вы также можете рассмотреть /(320|480|540)\/(light|dark|play)/ , что дает вам 9 комбинаций или более общую форму /[0-9]+\/(light|dark|play)/ (любое число, за которым следуют косая черта и одна из « светлых », « темных » и « играющих ») или даже /[0-9]+\/\w+/ (любое число, за которым следует косая черта и слово aka [A-Za-z0-9_]+ ). Все зависит от того, насколько строго или широко вы хотите, чтобы фильтр был.

 #!/system/bin/sh -xv Z=/absolute/path/to/WorkingDir T=320 F=480 # ? I=540 # ? D=dark L=light P=play # ? cd $Z for dir in $Z*/*/; do if [ -d $Z/$T/$D ] && [ ! -f $T$D.zip ]; then zip -0rq $T$D.zip $dir; elif [ -d $Z/$T/$L ] && [ ! -f $T$L.zip ]; then # elif rules zip -0rq $T$L.zip $dir; # It's not very efficient to scale this up, but you could add more elif statements here. elif [ -d $Z/$F/$D ] && [ ! -f $F$D.zip]; then zip -0rq $F$D.zip $dir; # and so on.. else exit fi; done 

Я думаю, что это все, что вам нужно. Сообщите мне, нужны ли какие-либо корректировки.

  • Извлеките один файл из zip-файла, только зная расширение
  • Восстановить содержимое файла Firefox .part?
  • архивирование файлов без изменений
  • Извлечение вложенных zip-файлов
  • Как распаковать каталог внутри zip-файла
  • Я неоднократно застегиваю одну и ту же папку с файлами, но shasum продолжает меняться
  • Unrar несколько частей
  • Текст с круговым отключением через zip, unzip с ошибкой «лишних байтов» в OS X
  • извлекать только определенную папку Содержимое из архива с zip-файлом в данный каталог
  • Создание справки для цикла для zip-файлов с определенным суффиксом и расширением
  • проблема с zip-файлом с использованием пароля
  • Найти рекурсивно все архивные файлы различных форматов архивов и искать их для шаблонов имен файлов
  • Linux и Unix - лучшая ОС в мире.