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

Я пока не знаю, в чем проблема, но у меня есть несколько замечаний о вашем сценарии.

Старайтесь не вызывать двоичные файлы (с одним фрагментом данных) в цикле. Это убивает производительность.

Вы должны вызвать весь сценарий с sudo, но не sudo в скрипте.

Для изменения имен файлов не требуется sed . bash может сделать это самостоятельно:

if [[ $dir =~ "Season 0" ]]; then
  new="${dir/Season 0/Sn}"
else
  new="${dir/Season /Sn}"
fi

Или без , если :

new="${dir/Season /Sn}"
new="${new/Sn0/Sn}"

Массив не нужен:

find ... | while read dirpath; do

Это имеет то «преимущество», что места в имени каталога не нарушают определение массива. Я понятия не имею, почему ваш массив = "$ (найти... -print) " работает. Он не должен (потому что оболочка не должна иметь разницы в разделении слов между космосом и новой строкой).

-121--175366-

Проблема заключается в том, что создается не массив, а последовательность. Вы можете легко проверить это, попытавшись напечатать первый элемент массива:

$ array="$(find . -maxdepth 2 -type d -iname 'Season*' -print)"; 
$ echo $array
./Season 3 ./Season 1 ./Season 2

Выглядит правильно? Но если бы это был массив, можно было бы напечатать каждый элемент отдельно. К сожалению, вышесказанное является простым рядом 1 , а не массивом:

$ echo ${array[0]}
./Season 3 ./Season 1 ./Season 2
$ echo ${array[1]}

Массив фактически состоит из одного ряда, из-за чего второй элемент «массива» ( $ {array [1]} ) пуст. В любом случае массив для этого не нужен, просто прочитайте выходные данные find (также не нужен -print , это то, что он делает по умолчанию). Рабочая версия вашего сценария может быть:

#!/usr/bin/env bash
find . -maxdepth 2 -type d -iname 'Season*' | sort -r |
while IFS= read -r dir
do 
    mv "$dir" ${dir/Season /Sn} && echo Changed "$dir" to "$dir/Season /Sn}"; 
done

Там используется пара трюков. Сначала выполните цикл while для просмотра результатов поиска . Это тот же самый основной принцип, что и для цикла , который вы использовали, но в сочетании с read могут считывать из стандартного ввода.

Во избежание разделения на пробелы IFS = (без него каталог Season 1 будет разделен на Season и 1 ).

В -r чтения указано, что нельзя использовать обратную косую черту для обхода символов (такие вещи, как \t и \n , обрабатываются буквально), что обеспечивает возможность использования даже самых странных имен.

sort -r необходим для того, чтобы при наличии каталога, соответствующего образцу, в другом соответствующем каталоге нижестоящий элемент был указан перед родительским. Например,

./Season 12/Season 13
./Season 12

Это обеспечивает запуск mv «Season 12» «Sn12» после running mv «Season 12 »/« Season 13» «Season 12 »/« Sn13» . Если этого не сделать, вторая команда завершится ошибкой, поскольку Season 12 больше не существует.

Наконец, я удалил sudo . Вместо этого следует запустить сценарий sudo script.sh . Никогда не рекомендуется использовать случайные sudo вызовы в сценариях.


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

0
07.02.2015, 13:38
2 ответа

Я получил сюда после получения разрешений на мое/домашнее подключение после изменения размера логического тома/root и/home. Я удалил и заново создал/home том и обнаружил, что/home нуждается в 755 разрешениях, чтобы позволить пользователям войти и получить доступ к своим/home/user каталогам. Я сделал: chmod 755/home и это сделал трюк.

-121--167417-

Необходимо указать зеркало CRAN; в интерактивном режиме в R выполните

chooseCRANmirror()

, чтобы выбрать соответствующее зеркало, затем

options("repos")

, чтобы увидеть результирующий URL. Вы можете добавить это навсегда в свою конфигурацию в ~/.Rprofile :

local({r <- getOption("repos")
   r["CRAN"] <- "<URL from above goes here>" 
   options(repos=r)
})
-121--166882-
#!/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

Я думаю, что это все, что вам нужно. Дайте мне знать, если это нуждается в каких-либо корректировках.

1
28.01.2020, 02:28

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

#!/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 , чтобы добавить то, что я назвал «хорошо известными именами каталогов».


РЕДАКТИРОВАТЬ : Добавление нескольких пояснений в соответствии с запросом OP.

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

Главный цикл

cd "$PWD/../WorkingDir"

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

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

Процедура сжатия

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

$ 1 - это аргумент, передаваемый в сжатый , то есть каталог для проверки и сжатия. Сначала 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 \ / (светлый | темный) / s @ / @ _ @ gp' более читабельным, чем '/ 320 \ / \ (светлый \ | темный \) / s @ / @ _ @ gp ' или ' / 320 \ / \ (светлый \ | темный \) / s / \ // _ / gp '.

: ${arch:=file}

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

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

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

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

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

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

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) / ( любое число, за которым следует косая черта и одно из « светлый », « темный » и « play ») или даже / [0-9] + \ / \ w + / (любое число, за которым следует косая черта и слово, также известное как [A-Za-z0-9 _] + ). Все зависит от того, насколько строгим или широким вы хотите, чтобы фильтр был.

2
28.01.2020, 02:28

Теги

Похожие вопросы